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; } } } }
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; }
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; }
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; }
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 {
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; }