Exemplo n.º 1
0
static void My_NPDU_Handler(
    BACNET_ADDRESS * src,       /* source address */
    uint8_t * pdu,      /* PDU data */
    uint16_t pdu_len)
{       /* length PDU  */
    int apdu_offset = 0;
    BACNET_ADDRESS dest = { 0 };
    BACNET_NPDU_DATA npdu_data = { 0 };

    apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
    if (npdu_data.network_layer_message) {
        if (apdu_offset <= pdu_len) {
            My_Router_Handler(src, &npdu_data, &pdu[apdu_offset],
                (uint16_t) (pdu_len - apdu_offset));
        }
    } else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) {
        if ((npdu_data.protocol_version == BACNET_PROTOCOL_VERSION) &&
            ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK))) {
            /* only handle the version that we know how to handle */
            /* and we are not a router, so ignore messages with
               routing information cause they are not for us */
            apdu_handler(src, &pdu[apdu_offset],
                (uint16_t) (pdu_len - apdu_offset));
        } else {
            if (dest.net) {
                debug_printf("NPDU: DNET=%d.  Discarded!\n", dest.net);
            } else {
                debug_printf("NPDU: BACnet Protocol Version=%d.  Discarded!\n",
                    npdu_data.protocol_version);
            }
        }
    }

    return;
}
Exemplo n.º 2
0
void testNPDU1(
    Test * pTest)
{
    uint8_t pdu[480] = { 0 };
    BACNET_ADDRESS dest = { 0 };
    BACNET_ADDRESS src = { 0 };
    BACNET_ADDRESS npdu_dest = { 0 };
    BACNET_ADDRESS npdu_src = { 0 };
    int len = 0;
    bool data_expecting_reply = false;
    BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL;
    BACNET_NPDU_DATA npdu_data = { 0 };
    int i = 0;  /* counter */
    int npdu_len = 0;
    bool network_layer_message = false; /* false if APDU */
    BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0;       /* optional */
    uint16_t vendor_id = 0;     /* optional, if net message type is > 0x80 */

    /* mac_len = 0 if global address */
    dest.mac_len = 0;
    for (i = 0; i < MAX_MAC_LEN; i++) {
        dest.mac[i] = 0;
    }
    /* DNET,DLEN,DADR */
    dest.net = 0;
    dest.len = 0;
    for (i = 0; i < MAX_MAC_LEN; i++) {
        dest.adr[i] = 0;
    }
    src.mac_len = 0;
    for (i = 0; i < MAX_MAC_LEN; i++) {
        src.mac[i] = 0;
    }
    /* SNET,SLEN,SADR */
    src.net = 0;
    src.len = 0;
    for (i = 0; i < MAX_MAC_LEN; i++) {
        src.adr[i] = 0;
    }
    npdu_encode_npdu_data(&npdu_data, false, priority);
    len = npdu_encode_pdu(&pdu[0], &dest, &src, &npdu_data);
    ct_test(pTest, len != 0);
    /* can we get the info back? */
    npdu_len = npdu_decode(&pdu[0], &npdu_dest, &npdu_src, &npdu_data);
    ct_test(pTest, npdu_len != 0);
    ct_test(pTest, npdu_data.data_expecting_reply == data_expecting_reply);
    ct_test(pTest, npdu_data.network_layer_message == network_layer_message);
    if (npdu_data.network_layer_message) {
        ct_test(pTest, npdu_data.network_message_type == network_message_type);
    }
    ct_test(pTest, npdu_data.vendor_id == vendor_id);
    ct_test(pTest, npdu_data.priority == priority);
    ct_test(pTest, npdu_dest.mac_len == src.mac_len);
    ct_test(pTest, npdu_src.mac_len == dest.mac_len);
}
Exemplo n.º 3
0
/** Handler for the NPDU portion of a received packet.
 *  Aside from error-checking, if the NPDU doesn't contain routing info,
 *  this handler doesn't do much besides stepping over the NPDU header
 *  and passing the remaining bytes to the apdu_handler.
 *  @note The routing (except src) and NCPI information, including
 *  npdu_data->data_expecting_reply, are discarded.
 * @see routing_npdu_handler
 *
 * @ingroup MISCHNDLR
 *
 * @param src  [out] Returned with routing source information if the NPDU
 *                   has any and if this points to non-null storage for it.
 *                   If src->net and src->len are 0 on return, there is no
 *                   routing source information.
 *                   This src describes the original source of the message when
 *                   it had to be routed to reach this BACnet Device, and this
 *                   is passed down into the apdu_handler; however, I don't
 *                   think this project's code has any use for the src info
 *                   on return from this handler, since the response has
 *                   already been sent via the apdu_handler.
 *  @param pdu [in]  Buffer containing the NPDU and APDU of the received packet.
 *  @param pdu_len [in] The size of the received message in the pdu[] buffer.
 */
void npdu_handler(
    PORT_SUPPORT *portParams,
    BACNET_ADDRESS * src,       /* source address */
    uint8_t * pdu,      /* PDU data */
    uint16_t pdu_len)
{       /* length PDU  */
    int apdu_offset = 0;
    BACNET_ADDRESS dest = { 0 };
    BACNET_NPDU_DATA npdu_data = { 0 };

    /* only handle the version that we know how to handle */
    if (pdu[0] == BACNET_PROTOCOL_VERSION) {
        apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
        if (npdu_data.network_layer_message) {
            /*FIXME: network layer message received!  Handle it! */
#if PRINT_ENABLED
            fprintf(stderr, "NPDU: Network Layer Message discarded!\n");
#endif
        } else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) {
            if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) {
                /* only handle the version that we know how to handle */
                /* and we are not a router, so ignore messages with
                   routing information cause they are not for us */
                if ((dest.net == BACNET_BROADCAST_NETWORK) &&
                    ((pdu[apdu_offset] & 0xF0) ==
                        PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) {
                    /* hack for 5.4.5.1 - IDLE */
                    /* ConfirmedBroadcastReceived */
                    /* then enter IDLE - ignore the PDU */
                } else {
                    apdu_handler(portParams, src, &pdu[apdu_offset],
                        (uint16_t) (pdu_len - apdu_offset));
                }
            } else {
#if PRINT_ENABLED
                printf("NPDU: DNET=%u.  Discarded!\n", (unsigned) dest.net);
#endif
            }
        }
    } else {
#if PRINT_ENABLED
        printf("NPDU: BACnet Protocol Version=%u.  Discarded!\n",
            (unsigned) pdu[0]);
#endif
    }

    return;
}
Exemplo n.º 4
0
static void mstp_monitor_i_am(
    uint8_t mac,
    uint8_t *pdu,
    uint16_t pdu_len)
{
    BACNET_ADDRESS src = { 0 };
    BACNET_ADDRESS dest = { 0 };
    BACNET_NPDU_DATA npdu_data = { 0 };
    int apdu_offset = 0;
    uint16_t apdu_len = 0;
    uint8_t *apdu = NULL;
    uint8_t pdu_type = 0;
    uint8_t service_choice = 0;
    uint8_t *service_request = NULL;
    uint32_t device_id = 0;
    int len = 0;

    if (pdu[0] == BACNET_PROTOCOL_VERSION) {
        MSTP_Fill_BACnet_Address(&src, mac);
        apdu_offset = npdu_decode(&pdu[0], &dest, &src, &npdu_data);
        if ((!npdu_data.network_layer_message) &&
            (apdu_offset > 0) && (apdu_offset < pdu_len) &&
            ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) &&
            (src.net == 0)) {
            apdu_len = pdu_len - apdu_offset;
            apdu = &pdu[apdu_offset];
            pdu_type = apdu[0] & 0xF0;
            if ((pdu_type == PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST) &&
                (apdu_len >= 2)) {
                service_choice = apdu[1];
                service_request = &apdu[2];
                if (service_choice == SERVICE_UNCONFIRMED_I_AM) {
                    len = iam_decode_service_request(service_request,
                        &device_id, NULL, NULL, NULL);
                    if (len != -1) {
                        MSTP_Statistics[mac].device_id = device_id;
                    }
                }
            }
        }
    }
}
Exemplo n.º 5
0
/** Handler for the NPDU portion of a received packet, which may have routing.
 *  This is a fuller handler than the regular npdu_handler, as it manages
 *  - Decoding of the NCPI byte
 *  - Further processing by network_control_handler() if this is a  network 
 *    layer message.
 *  - Further processing by routed_apdu_handler() if it contains an APDU
 *    - Normally (no routing) by apdu_handler()
 *    - With Routing (a further destination was indicated) by the decoded
 *      destination.
 *  - Errors in decoding.
 * @note The npdu_data->data_expecting_reply status is discarded.
 * @see npdu_handler
 * @ingroup NMRC
 *  
 * @param src  [out] Returned with routing source information if the NPDU 
 *                   has any and if this points to non-null storage for it. 
 *                   If src->net and src->len are 0 on return, there is no
 *                   routing source information.
 *                   This src describes the original source of the message when
 *                   it had to be routed to reach this BACnet Device, and this
 *                   is passed down into the apdu_handler; however, I don't 
 *                   think this project's code has any use for the src info  
 *                   on return from this handler, since the response has 
 *                   already been sent via the apdu_handler.
 * @param DNET_list [in] List of our reachable downstream BACnet Network numbers.
 * 					 Normally just one valid entry; terminated with a -1 value.
 *  @param pdu [in]  Buffer containing the NPDU and APDU of the received packet.
 *  @param pdu_len [in] The size of the received message in the pdu[] buffer.
 */
void routing_npdu_handler(
    BACNET_ADDRESS * src,
    int *DNET_list,
    uint8_t * pdu,
    uint16_t pdu_len)
{
    int apdu_offset = 0;
    BACNET_ADDRESS dest = { 0 };
    BACNET_NPDU_DATA npdu_data = { 0 };

    /* only handle the version that we know how to handle */
    if (pdu[0] == BACNET_PROTOCOL_VERSION) {
        apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
        if (apdu_offset <= 0) {
            debug_printf("NPDU: Decoding failed; Discarded!\n");
        } else if (npdu_data.network_layer_message) {
            if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) {
                network_control_handler(src, DNET_list, &npdu_data,
                    &pdu[apdu_offset], (uint16_t) (pdu_len - apdu_offset));
            } else {
                /* The DNET is set, but we don't support downstream routers,
                 * so we just silently drop this network layer message,
                 * since only routers can handle it (even if for our DNET) */
            }
        } else if (apdu_offset <= pdu_len) {
            if ((dest.net == 0) || (npdu_data.hop_count > 1))
                routed_apdu_handler(src, &dest, DNET_list, &pdu[apdu_offset],
                    (uint16_t) (pdu_len - apdu_offset));
            /* Else, hop_count bottomed out and we discard this one. */
        }
    } else {
        /* Should we send NETWORK_MESSAGE_REJECT_MESSAGE_TO_NETWORK? */
        debug_printf
            ("NPDU: Unsupported BACnet Protocol Version=%u.  Discarded!\n",
            (unsigned) pdu[0]);
    }

    return;
}
Exemplo n.º 6
0
/** Handler for the NPDU portion of a received packet.
 *  Aside from error-checking, if the NPDU doesn't contain routing info,
 *  this handler doesn't do much besides stepping over the NPDU header
 *  and passing the remaining bytes to the apdu_handler.
 *  @note The routing (except src) and NCPI information, including 
 *  npdu_data->data_expecting_reply, are discarded.
 * @see routing_npdu_handler
 *  
 * @ingroup MISCHNDLR
 *  
 * @param src  [out] Returned with routing source information if the NPDU 
 *                   has any and if this points to non-null storage for it. 
 *                   If src->net and src->len are 0 on return, there is no
 *                   routing source information.
 *                   This src describes the original source of the message when
 *                   it had to be routed to reach this BACnet Device, and this
 *                   is passed down into the apdu_handler; however, I don't 
 *                   think this project's code has any use for the src info  
 *                   on return from this handler, since the response has 
 *                   already been sent via the apdu_handler.
 *  @param pdu [in]  Buffer containing the NPDU and APDU of the received packet.
 *  @param pdu_len [in] The size of the received message in the pdu[] buffer.
 */
void npdu_handler(
    BACNET_ADDRESS * src,       /* source address */
    uint8_t * pdu,      /* PDU data */
    uint16_t pdu_len)
{       /* length PDU  */
    int apdu_offset = 0;
    BACNET_ADDRESS dest = { 0 };
    BACNET_NPDU_DATA npdu_data = { 0 };

    /* only handle the version that we know how to handle */
    if (pdu[0] == BACNET_PROTOCOL_VERSION) {
        apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
        if (npdu_data.network_layer_message) {
            /*FIXME: network layer message received!  Handle it! */
#ifdef PRINT_ENABLE
            fprintf(stderr, "NPDU: Network Layer Message discarded!\n");
#endif
        } else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) {
            if ((dest.net == 0) || (dest.net == BACNET_BROADCAST_NETWORK)) {
                /* only handle the version that we know how to handle */
                /* and we are not a router, so ignore messages with
                   routing information cause they are not for us */
                apdu_handler(src, &pdu[apdu_offset],
                    (uint16_t) (pdu_len - apdu_offset));
            } else {
#ifdef PRINT_ENABLE
                fprintf(stderr, "NPDU: DNET=%u.  Discarded!\n", (unsigned) dest.net);
#endif
            }
        }
    } else {
#ifdef PRINT_ENABLE
        fprintf(stderr, "NPDU: BACnet Protocol Version=%u.  Discarded!\n",
            (unsigned) pdu[0]);
#endif
    }

    return;
}
Exemplo n.º 7
0
bool dlmstp_compare_data_expecting_reply(
    uint8_t * request_pdu,
    uint16_t request_pdu_len,
    uint8_t src_address,
    uint8_t * reply_pdu,
    uint16_t reply_pdu_len,
    BACNET_ADDRESS * dest_address)
{
    uint16_t offset;
    /* One way to check the message is to compare NPDU
       src, dest, along with the APDU type, invoke id.
       Seems a bit overkill */
    struct DER_compare_t {
        BACNET_NPDU_DATA npdu_data;
        BACNET_ADDRESS address;
        uint8_t pdu_type;
        uint8_t invoke_id;
        uint8_t service_choice;
    };
    struct DER_compare_t request;
    struct DER_compare_t reply;

    /* unused parameters */
    request_pdu_len = request_pdu_len;
    reply_pdu_len = reply_pdu_len;
    /* decode the request data */
    request.address.mac[0] = src_address;
    request.address.mac_len = 1;
    offset =
        npdu_decode(&request_pdu[0], NULL, &request.address,
        &request.npdu_data);
    if (request.npdu_data.network_layer_message) {
        return false;
    }
    request.pdu_type = request_pdu[offset] & 0xF0;
    if (request.pdu_type != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) {
        return false;
    }
    request.invoke_id = request_pdu[offset + 2];
    /* segmented message? */
    if (request_pdu[offset] & BIT3)
        request.service_choice = request_pdu[offset + 5];
    else
        request.service_choice = request_pdu[offset + 3];
    /* decode the reply data */
    bacnet_address_copy(&reply.address, dest_address);
    offset =
        npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
    if (reply.npdu_data.network_layer_message) {
        return false;
    }
    /* reply could be a lot of things:
       confirmed, simple ack, abort, reject, error */
    reply.pdu_type = reply_pdu[offset] & 0xF0;
    switch (reply.pdu_type) {
        case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
            reply.invoke_id = reply_pdu[offset + 2];
            /* segmented message? */
            if (reply_pdu[offset] & BIT3)
                reply.service_choice = reply_pdu[offset + 5];
            else
                reply.service_choice = reply_pdu[offset + 3];
            break;
        case PDU_TYPE_SIMPLE_ACK:
            reply.invoke_id = reply_pdu[offset + 1];
            reply.service_choice = reply_pdu[offset + 2];
            break;
        case PDU_TYPE_COMPLEX_ACK:
            reply.invoke_id = reply_pdu[offset + 1];
            /* segmented message? */
            if (reply_pdu[offset] & BIT3)
                reply.service_choice = reply_pdu[offset + 4];
            else
                reply.service_choice = reply_pdu[offset + 2];
            break;
        case PDU_TYPE_ERROR:
            reply.invoke_id = reply_pdu[offset + 1];
            reply.service_choice = reply_pdu[offset + 2];
            break;
        case PDU_TYPE_REJECT:
        case PDU_TYPE_ABORT:
            reply.invoke_id = reply_pdu[offset + 1];
            break;
        default:
            return false;
    }
    /* these don't have service choice included */
    if ((reply.pdu_type == PDU_TYPE_REJECT) ||
        (reply.pdu_type == PDU_TYPE_ABORT)) {
        if (request.invoke_id != reply.invoke_id) {
            return false;
        }
    } else {
        if (request.invoke_id != reply.invoke_id) {
            return false;
        }
        if (request.service_choice != reply.service_choice) {
            return false;
        }
    }
    if (request.npdu_data.protocol_version != reply.npdu_data.protocol_version) {
        return false;
    }
    if (request.npdu_data.priority != reply.npdu_data.priority) {
        return false;
    }
    if (!bacnet_address_same(&request.address, &reply.address)) {
        return false;
    }

    return true;
}