Example #1
0
void parse_dhcp_options(ppe_packet_t *ppep, int len, int cmp, int dump)
{
    struct dhcp_packet  *dhcp_pkt;
    int                 dhcp_pkt_len;
    int                 dhcp_opt_len;
    uint8_t             *dhcp_expected = NULL;
    int                 dhcp_expected_len = 0;
    int                 match_index = 0;
    if (!(dhcp_pkt = (struct dhcp_packet*)ppe_header_get(ppep, PPE_HEADER_DHCP))) {
        printf("NOT DHCP packet");
        return;
    }

    dhcp_pkt_len = ppe_header_get(ppep, PPE_HEADER_ETHERNET) + len 
                   - ppe_header_get(ppep, PPE_HEADER_DHCP);
    dhcp_opt_len = dhcp_pkt_len - ((uint8_t*)&(dhcp_pkt->options) - (uint8_t*)dhcp_pkt);

    if (dump) {
        printf("dhcp_pkt_len=%d, opt_len=%d\n",dhcp_pkt_len,dhcp_opt_len);
        printf("hexdump: dhcp option portion only\n");
        hexdump(&(dhcp_pkt->options), dhcp_opt_len);
        printf("hexdump: dhcp pkt\n");
        hexdump_pkt((uint8_t*)dhcp_pkt, dhcp_pkt_len);
    }

    if (cmp) {
        if (dhcp_pkt->op == BOOTREQUEST){
            dhcp_expected = Dhcp_discovery_expected;
            dhcp_expected_len = sizeof(Dhcp_discovery_expected);
        } else if (dhcp_pkt->op == BOOTREPLY) {
            dhcp_expected = Dhcp_offer_expected;
            dhcp_expected_len = sizeof(Dhcp_offer_expected);
            match_index = 1;
        } else {
            printf("ERROR UNSUPPORTED DHCP TYPE %d\n", dhcp_pkt->op);
        }

        if ( dhcp_expected_len !=  dhcp_pkt_len){
            printf("DCHP pkt len:%u, expected %u", dhcp_pkt_len,dhcp_expected_len);
            return;
        }

        if (dhcp_expected) {
            if (memcmp(dhcp_expected, dhcp_pkt, dhcp_expected_len))
                printf("DCHP pkt:    FAILED");
            else {
                printf("DCHP pkt:    MATCHED");
                dhcp_pkt_matched[match_index] = 1;
            }
        }
    }
}
Example #2
0
static ucli_status_t
ppe_ucli_utm__setheader__(ucli_context_t* uc)
{
    uint8_t* data; 
    int size; 
    ppe_header_t header; 

    UCLI_COMMAND_INFO(uc, 
                      "setheader", 2, 
                      "Set header data."); 


    UCLI_ARGPARSE_OR_RETURN(uc, "{ppe_header}{data}", &header, &data, &size); 
    if(ppe_header_get(&ppec->ppep, header)) { 
        aim_free(ppe_header_get(&ppec->ppep, header)); 
    }
    if(ppe_header_set(&ppec->ppep, header, data) < 0) {
        return ucli_e_internal(uc, "ppe_set_header()"); 
    }
    return UCLI_STATUS_OK; 
}
Example #3
0
void get_dhcp_options(ppe_packet_t *ppep, int len, int dump, int *option)
{
    struct dhcp_packet  *dhcp_pkt;
    int                 dhcp_pkt_len;
    int                 dhcp_opt_len;

    if (!(dhcp_pkt = (struct dhcp_packet*)ppe_header_get(ppep, PPE_HEADER_DHCP))) {
        printf("NOT DHCP packet");
        return;
    }

    dhcp_pkt_len = ppe_header_get(ppep, PPE_HEADER_ETHERNET) + len 
                   - ppe_header_get(ppep, PPE_HEADER_DHCP);
    dhcp_opt_len = dhcp_pkt_len - ((uint8_t*)&(dhcp_pkt->options) - (uint8_t*)dhcp_pkt);

    if(dump) {
        printf("dhcp_pkt_len=%d, opt_len=%d\n",dhcp_pkt_len,dhcp_opt_len);
        hexdump(&(dhcp_pkt->options), dhcp_opt_len);
        hexdump_pkt((uint8_t*)dhcp_pkt, dhcp_pkt_len);
    }
    
    *option = dhcp_pkt->op;
}
Example #4
0
void
icmpa_verify_packet (of_octets_t *octets, uint32_t reason)
{
    ppe_packet_t               ppep;
    uint32_t                   icmp_type;

    if (!octets) return;

    ppe_packet_init(&ppep, octets->data, octets->bytes);    
    if (ppe_parse(&ppep) < 0) {
        AIM_LOG_ERROR("Packet_in parsing failed.");
        return;
    }

    assert(ppe_header_get(&ppep, PPE_HEADER_ICMP)); 
    ppe_field_get(&ppep, PPE_FIELD_ICMP_TYPE, &icmp_type);
    assert(icmp_type == reason); 
}
/*
 * lacpa_receive
 *
 * Process incoming LACPDU and take appropriate action
 */
extern bool
lacpa_receive (lacpa_port_t *port, uint8_t *data, uint32_t bytes)
{
    lacpa_pdu_t  pdu;
    ppe_packet_t ppep;

	if (!port || !data) return FALSE;

    if (!port->lacp_enabled) {
        AIM_LOG_ERROR("LACPDU-Rx-FAILED - Agent is Disabled on port: %d",
                      port->actor.port_no);
		return FALSE;
    }

    LACPA_MEMSET(&pdu, DEFAULT_ZERO, sizeof(lacpa_pdu_t));
    AIM_LOG_TRACE("LACPDU Received on port: %d", port->actor.port_no);

    /*
     * Use ppe api's to fill info from data in our pdu
     */
    ppe_packet_init(&ppep, data, bytes);
    if (ppe_parse(&ppep) < 0) {
        AIM_LOG_ERROR("Packet parsing failed. packet=%{data}", data, bytes);
        return FALSE;
    }

    if (!ppe_header_get(&ppep, PPE_HEADER_LACP)) {
        AIM_LOG_ERROR("Not a Valid LCAP Packet");
        return FALSE;
    }

	/*
     * Retrieve the information from the LCAP packet
     */
    if (!lacpa_parse_pdu(&ppep, &pdu)) {
		AIM_LOG_ERROR("Packet parsing failed.");
        return FALSE;
    }

    port->lacp_event = LACPA_EVENT_PDU_RECEIVED;
    lacpa_machine(port, &pdu);

    return TRUE;
}
Example #6
0
indigo_error_t
dhcpra_create_send_packet_in (of_port_no_t in_port, of_octets_t *of_octets)
{
    of_packet_in_t *of_packet_in;
    of_match_t     match;
    ppe_packet_t   ppep;
    ppe_header_t   format;
    uint8_t        buf[1500];
    int            option;

    int debug_dump = 0;
    if (!of_octets) return INDIGO_ERROR_UNKNOWN;

    /*
     * Check if the packet_in is untagged, then add the Vlan tag 
     */
    ppe_packet_init(&ppep, of_octets->data, of_octets->bytes);
    if (ppe_parse(&ppep) < 0) {
        printf("RAW untag linux packet parsing failed.\n");
        return INDIGO_ERROR_UNKNOWN;
    } 

    if (!(ppe_header_get(&ppep, PPE_HEADER_DHCP))) {
        /* Since we listen to all pkt_in
         * Rate is high, no need add debug msg here
         * Not LLDP packet, simply return */
        printf("in_port=%u: NOT DHCP packet IGNORED", in_port);
        return INDIGO_ERROR_NONE;
    }

    /* Dump up to DHCP hdr */
    printf("RAW untag Linux dump\n");
    get_dhcp_options(&ppep, of_octets->bytes, debug_dump, &option);

    ppe_packet_format_get(&ppep, &format);
    if (format != PPE_HEADER_8021Q) {
        of_octets->bytes += 4;
        memcpy(buf, of_octets->data, of_octets->bytes);
        memcpy(of_octets->data+16, buf+12, of_octets->bytes-16);
        of_octets->data[12] = ETHERTYPE_DOT1Q >> 8;
        of_octets->data[13] = ETHERTYPE_DOT1Q & 0xFF;
        of_octets->data[14] = 0;
        of_octets->data[15] = VLAN_TEST; //7;  
    } else {
Example #7
0
static ucli_status_t
ppe_ucli_utm__rwall__(ucli_context_t* uc)
{
    ppe_packet_t ppep;  
    ppe_header_t header; 
    ppe_field_t f; 
    int rv = UCLI_STATUS_OK; 

    UCLI_COMMAND_INFO(uc, 
                      "rwall", 0, 
                      "Read and write all packet fields in all headers."); 

    ppe_packet_init(&ppep, NULL, 0);

    /**
     * Allocate and assign a header pointer for every header type. 
     * All bits will be initialized to 1. 
     */
    for(header = 0; header < PPE_HEADER_COUNT; header++) {
        uint8_t* hp = aim_zmalloc(1000); 
        PPE_MEMSET(hp, 0xFF, 1000); 
        ppe_header_set(&ppep, header, hp); 
    }

    /**
     * Check that every field reads back as all 1's, with the correct width
     */
    for(f = 0; f < PPE_FIELD_COUNT; f++) {
        const ppe_field_info_t* fi = ppe_field_info_get(f); 
        if(fi->size_bits == 0) { 
            continue; 
        }
        if(fi->size_bits <= 32) {
            uint32_t v;
            ppe_field_get(&ppep, f, &v); 
            if(fi->size_bits == 32) {
                if(v != 0xFFFFFFFF)  {
                    rv = ucli_error(uc, "first read: field %{ppe_field} is 0x%x, should be 0x%x", 
                                    f, v, -1); 
                }
            }
            else {
                if(v != ( (1U << fi->size_bits) - 1)) { 
                    rv = ucli_error(uc, "first read: field %{ppe_field} is 0x%x, should be 0x%x (%d bits)", 
                                    f, v, (1<<fi->size_bits) - 1, fi->size_bits); 
                }
            }
            /** clear field and re-read */
            ppe_field_set(&ppep, f, 0); 
            ppe_field_get(&ppep, f, &v); 
            if(v != 0) {
                rv = ucli_error(uc, "second read: field %{ppe_field} is 0x%x when it should be 0.", 
                                f, v); 
            }            
        }
        else {
            uint8_t vb[64];    
            int bytes = ppe_wide_field_get(&ppep, f, vb); 
            int i; 
            for(i = 0; i < bytes; i++) {
                if(vb[i] != 0xFF) { 
                    rv = ucli_error(uc, "first read: field %{ppe_field}[%d] is 0x%.2x, should be 0x%.2x", 
                                    f, i, vb[i], 0xFF); 
                }
            }
            PPE_MEMSET(vb, 0, sizeof(vb)); 
            /** clear field and re-read */
            ppe_wide_field_set(&ppep, f, vb); 
            PPE_MEMSET(vb, 0xFF, sizeof(vb)); 
            ppe_wide_field_get(&ppep, f, vb); 
            for(i = 0; i < bytes; i++) {
                if(vb[i] != 0) {
                    rv = ucli_error(uc, "second read: field %{ppe_field}[%d] is 0x%.2x, should be 0.", 
                                    f, i, vb[i]); 
                }
            }
        }

        /** continue reading other fields, making sure the field we just cleared
         * does not change the value of fields we have not yet visited. */

    }

    for(header = 0; header < PPE_HEADER_COUNT; header++) {
        aim_free(ppe_header_get(&ppep, header)); 
    }
    return rv; 
}
/*
 * icmp_packet_in_handler
 *
 * API for handling incoming packets
 */
indigo_core_listener_result_t
icmpa_packet_in_handler (of_packet_in_t *packet_in)
{
    of_octets_t                octets;
    of_port_no_t               port_no;
    of_match_t                 match;
    ppe_packet_t               ppep;
    indigo_core_listener_result_t result = INDIGO_CORE_LISTENER_RESULT_PASS;
    uint32_t                   type, code;

    debug_counter_inc(&pkt_counters.icmp_total_in_packets);
    if (!packet_in) return INDIGO_CORE_LISTENER_RESULT_PASS;

    of_packet_in_data_get(packet_in, &octets);

    /*
     * Identify the recv port
     */
    if (packet_in->version <= OF_VERSION_1_1) {
        return INDIGO_CORE_LISTENER_RESULT_PASS;
    } else {
        if (of_packet_in_match_get(packet_in, &match) < 0) {
            AIM_LOG_ERROR("ICMPA: match get failed");
            debug_counter_inc(&pkt_counters.icmp_internal_errors);
            return INDIGO_CORE_LISTENER_RESULT_PASS;
        }
        port_no = match.fields.in_port;
    }

    if (port_no == OF_PORT_DEST_CONTROLLER) {
        debug_counter_inc(&pkt_counters.icmp_total_passed_packets);
        return INDIGO_CORE_LISTENER_RESULT_PASS;
    }

    if (port_no > MAX_PORTS) {
        AIM_LOG_ERROR("ICMPA: Port No: %d Out of Range %d", port_no, MAX_PORTS);
        debug_counter_inc(&pkt_counters.icmp_internal_errors);
        return INDIGO_CORE_LISTENER_RESULT_PASS;
    }

    /*
     * Check the packet-in reasons in metadata
     *
     * Icmp agent should not consume packets coming in due to L2 Src miss
     * and Station Move.
     */
    if ((match.fields.metadata & OFP_BSN_PKTIN_FLAG_STATION_MOVE) ||
        (match.fields.metadata & OFP_BSN_PKTIN_FLAG_NEW_HOST)) {
        debug_counter_inc(&pkt_counters.icmp_total_passed_packets);
        return INDIGO_CORE_LISTENER_RESULT_PASS;
    }

    ppe_packet_init(&ppep, octets.data, octets.bytes);
    if (ppe_parse(&ppep) < 0) {
        AIM_LOG_RL_ERROR(&icmp_pktin_log_limiter, os_time_monotonic(),
                         "ICMPA: Packet_in parsing failed.");
        debug_counter_inc(&pkt_counters.icmp_internal_errors);
        return INDIGO_CORE_LISTENER_RESULT_PASS;
    }

    /*
     * Identify if this is an Echo Request, destined to one of VRouter
     */
    if (ppe_header_get(&ppep, PPE_HEADER_ICMP)) {
        if (icmpa_reply(&ppep, port_no, &result)) {
            ++port_pkt_counters[port_no].icmp_echo_packets;
            return result;
        }
    }

    /*
     * To handle traceroute, we need to check for
     * a) UDP Packet
     * b) dest IP is Vrouter IP
     * c) UDP src and dest ports are ephemeral
     */
    if (ppe_header_get(&ppep, PPE_HEADER_UDP) &&
        ppe_header_get(&ppep, PPE_HEADER_IP4)) {
        uint32_t dest_ip, src_port, dest_port;
        ppe_field_get(&ppep, PPE_FIELD_IP4_DST_ADDR, &dest_ip);
        ppe_field_get(&ppep, PPE_FIELD_UDP_SRC_PORT, &src_port);
        ppe_field_get(&ppep, PPE_FIELD_UDP_DST_PORT, &dest_port);

        if (router_ip_check(dest_ip) && is_ephemeral(src_port) &&
            is_ephemeral(dest_port)) {
            AIM_LOG_TRACE("ICMP Port Unreachable received on port: %d",
                          port_no);
            type = ICMP_DEST_UNREACHABLE;
            code = 3;
            result = INDIGO_CORE_LISTENER_RESULT_DROP;
            if (icmpa_send(&ppep, port_no, type, code)) {
                ++port_pkt_counters[port_no].icmp_port_unreachable_packets;
                return result;
            }
        }
    }

    /*
     * Identify if the reason is valid for ICMP Agent to consume the packet
     */
    if (match.fields.metadata & OFP_BSN_PKTIN_FLAG_L3_MISS) {
        AIM_LOG_TRACE("ICMP Dest Network Unreachable received on port: %d",
                      port_no);
        type = ICMP_DEST_UNREACHABLE;
        code = 0;
        result = INDIGO_CORE_LISTENER_RESULT_DROP;
        if (icmpa_send(&ppep, port_no, type, code)) {
            ++port_pkt_counters[port_no].icmp_net_unreachable_packets;
        }
    } else if (match.fields.metadata & OFP_BSN_PKTIN_FLAG_TTL_EXPIRED) {
        AIM_LOG_TRACE("ICMP TTL Expired received on port: %d", port_no);
        type = ICMP_TIME_EXCEEDED;
        code = 0;
        result = INDIGO_CORE_LISTENER_RESULT_DROP;
        if (icmpa_send(&ppep, port_no, type, code)) {
            ++port_pkt_counters[port_no].icmp_time_exceeded_packets;
        }
    }

    return result;
}