Beispiel #1
0
OT_WEAK ot_u16 otapi_close_request() {
/// Set the footer if the session is valid
    if (session_notempty()) {
        m2np_footer( /* session_top() */ );
        return 1;
    }
    return 0;
}
Beispiel #2
0
OT_WEAK void dll_beacon_applet(m2session* active) {
/// Beaconing is a Request-TX operation, and the value for Tc is the amount of
/// time to spend in CSMA before quitting the beacon.
    ot_queue beacon_queue;
    ot_u8 b_params;
    ot_u8 cmd_ext;
    ot_u8 cmd_code;

    b_params        = active->extra;
    active->extra   = 0;

    /// Start building the beacon packet:
    /// <LI> Calling m2np_header() will write most of the front of the frame </LI>
    /// <LI> Add the command byte and optional command-extension byte </LI>
    m2np_header(active, M2RT_BROADCAST, M2FI_FRDIALOG);

    cmd_ext     = (b_params & 0x06);                            // Normal extension bits
    cmd_ext    |= (dll.netconf.btemp[2] == 0) << 6;             // Announcement No-File bit
    cmd_code    = 0x20 | (b_params & 1) | ((cmd_ext!=0) << 7);
    q_writebyte(&txq, cmd_code);
    if (cmd_code) {
        q_writebyte(&txq, cmd_ext);
    }

    /// Setup the comm parameters, if the channel is available:
    /// <LI> dll.comm values tx_eirp, cs_rssi, and cca_rssi must be set by the
    ///      radio module during the CSMA-CA process -- don't set them here.
    ///      The DASH7 spec requires it to happen in this order. </LI>
    /// <LI> Set CSMA-CA parameters, which are used by the radio module </LI>
    /// <LI> Set number of redundant TX's we would like to transmit </LI>
    /// <LI> Set rx_timeout for Default-Tg or 0, if beacon has no response </LI>
    dll_set_defaults(active);
    dll.comm.tc             = TI2CLK(M2_PARAM_BEACON_TCA);
    dll.comm.rx_timeout     = (b_params & 0x02) ? \
                                0 : rm2_default_tgd(active->channel);
    dll.comm.csmaca_params |= (b_params & 0x04) | M2_CSMACA_NA2P | M2_CSMACA_MACCA;
    dll.comm.redundants     = dll.netconf.b_attempts;

    q_writebyte(&txq, (ot_u8)dll.comm.rx_timeout);

    /// Add the announcement file data if the specified return data != 0 bytes.
    /// If the beacon data is missing or otherwise not accessible by the GUEST
    /// user, dump the session (thus killing the beacon) and go back to idle.
    if (dll.netconf.btemp[2] != 0) {
        q_init(&beacon_queue, &dll.netconf.btemp[2], 4);
        if (m2qp_isf_call((b_params & 1), &beacon_queue, AUTH_GUEST) < 0) {
            session_pop();
            dll_idle();
            return;
        }
    }

    /// Final step to any packet generation: add footer
    m2np_footer();
}
Beispiel #3
0
void m2dp_footer() {
/// M2DP is similar enough to M2NP that the same footer function may be used.
    m2np_footer();
}
Beispiel #4
0
ot_int network_route_ff(m2session* session) {
    ot_int route_val;

    /// Strip CRC (-2 bytes)
    rxq.front[0] -= 2;
    
    /// Acquire Flags and Protocol from the Frame Info Field
    rxq.getcursor       = &rxq.front[3];
    session->protocol   = (*rxq.getcursor & M2FI_FRTYPEMASK);
    session->flags      = *rxq.getcursor & 0xC0;
    m2np.header.fr_info = *rxq.getcursor++;
    
    /// Treat Non-Mode-2 Protocols
    /// @note Non-Mode-2 protocols not supported at this time
    if (m2np.header.fr_info & M2FI_NM2) {
        return -1;
    }
    
    /// Data Link Layer Security
    if (m2np.header.fr_info & M2FI_DLLS) {
#   if (OT_FEATURE(DLL_SECURITY))
        ///@todo experimental
        AES_load_static_key(ISF_ID(user_authentication_key), (ot_u32*)txq.front);
        AES_keyschedule_dec((ot_u32*)txq.front, (ot_u32*)(txq.front+16));
        AES_decrypt(rxq.getcursor, rxq.getcursor, (ot_u32*)(txq.front+16));
#   else
        return -1;
#   endif
    }
    
    /// Address Control Header (Present in M2NP)
    /// Session Connection and Dialog Filtering:
    /// - if unassociated, connect now
    /// - if already connected, make sure the dialog IDs are equal
    if (m2np.header.fr_info & M2FI_ENADDR) {
        if (session->netstate & M2_NETSTATE_CONNECTED) {
            if (session->dialog_id != q_readbyte(&rxq)) {
                return -1;
            }
        }
        else {
            session->netstate  |= M2_NETSTATE_CONNECTED;
            session->subnet     = rxq.front[2];
            session->dialog_id  = q_readbyte(&rxq);
        }
        
        /// Grab global flags from Address Control
        m2np.header.addr_ctl    = q_readbyte(&rxq);
        session->flags         |= m2np.header.addr_ctl & 0x3F;
        
        /// Grab Source Address from this packet (dialog address), which is 
        /// converted to the target address in the response.
        m2np.rt.dlog.length = (m2np.header.addr_ctl & M2_FLAG_VID) ? 2 : 8;
        m2np.rt.dlog.value  = q_markbyte(&rxq, m2np.rt.dlog.length);
        
        /// Network Layer Security
        /// @note Network Layer Security not supported at this time
        if (m2np.header.addr_ctl & M2_FLAG_NLS) {
#       if (OT_FEATURE(NL_SECURITY))
#       else
            return -1;
#       endif
        }
        
        /// If unicasting, the next data is the target address, which will have
        /// the same length as the source address, and it needs to match this
        /// device's device ID (VID or UID)
        if ((m2np.header.addr_ctl & 0xC0) == 0) {
            session->netstate |= M2_NETFLAG_FIRSTRX;
            if ( !m2np_idcmp(m2np.rt.dlog.length, q_markbyte(&rxq, m2np.rt.dlog.length)) ) {
                return -1;
            }
        }
    }

    /// Vector to the appropriate Network Layer Protocol Parser
    /// Most network protocols don't do anything except broadcast.  M2NP is the
    /// exception, and it manages various types of routing at the network layer.
    route_val = -1;
    switch (session->protocol & M2FI_FRTYPEMASK) {
    	case M2FI_FRDIALOG:
        case M2FI_FRNACK: {
            // Reset routing template
            m2np.rt.hop_code    = 0;
            m2np.rt.hop_ext     = 0;
            m2np.rt.orig.value  = NULL;
            m2np.rt.dest.value  = NULL;
            
            /// Unicast and Anycast Requests have a routing template
            /// (Not currently supported, so just move the cursor ahead)
            if ((m2np.header.addr_ctl & 0x40) == 0) {
                m2np.rt.hop_code    = q_readbyte(&rxq);
                m2np.rt.orig.length = ((m2np.rt.hop_code & M2HC_VID) != 0) ? 2 : 8;                       
                m2np.rt.dest.length = m2np.rt.orig.length;
                
                if ((m2np.rt.hop_code & M2HC_EXT) != 0) {
                    m2np.rt.hop_ext = q_readbyte(&rxq);
                }
                if ((m2np.rt.hop_code & M2HC_ORIG) != 0) {
                    m2np.rt.orig.value = q_markbyte(&rxq, m2np.rt.orig.length);
                }
                if ((m2np.rt.hop_code & M2HC_DEST) != 0) {
                    m2np.rt.dest.value = q_markbyte(&rxq, m2np.rt.dest.length);
                }
            }
        } // Note case fall-through
    
        case M2FI_STREAM: {
            /// M2DP gets parsed just like M2NP, but it uses the Network data
        	/// stored from the last M2NP frame
            route_val = m2qp_parse_frame(session);
            break;
        }
        
        case M2FI_RFU: break;
    }
    
    /// Attach footer to response, if necessary
    if (route_val >= 0) {
        m2np_footer(session);
    }

#   if (OT_FEATURE(M2NP_CALLBACKS) == ENABLED) && \
        !defined(EXTF_network_sig_route)
        m2np.signal.route(route_val, session->protocol);
#   elif defined(EXTF_network_sig_route)
        network_sig_route(route_val, session->protocol);
#   endif
    
    return route_val;
}