/* *------------------------------------------------------------------ * ip_api.c - vnet ip api * * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define vl_typedefs /* define message structures */ #include #undef vl_typedefs #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include #undef vl_printfun #include #define foreach_ip_api_msg \ _(IP_FIB_DUMP, ip_fib_dump) \ _(IP6_FIB_DUMP, ip6_fib_dump) \ _(IP_MFIB_DUMP, ip_mfib_dump) \ _(IP6_MFIB_DUMP, ip6_mfib_dump) \ _(IP_NEIGHBOR_DUMP, ip_neighbor_dump) \ _(IP_MROUTE_ADD_DEL, ip_mroute_add_del) \ _(MFIB_SIGNAL_DUMP, mfib_signal_dump) \ _(IP_ADDRESS_DUMP, ip_address_dump) \ _(IP_DUMP, ip_dump) \ _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \ _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit) \ _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \ _(WANT_IP6_ND_EVENTS, want_ip6_nd_events) \ _(PROXY_ARP_ADD_DEL, proxy_arp_add_del) \ _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \ _(RESET_FIB, reset_fib) \ _(IP_ADD_DEL_ROUTE, ip_add_del_route) \ _(IP_TABLE_ADD_DEL, ip_table_add_del) \ _(IP_PUNT_POLICE, ip_punt_police) \ _(IP_PUNT_REDIRECT, ip_punt_redirect) \ _(SET_IP_FLOW_HASH,set_ip_flow_hash) \ _(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config) \ _(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix) \ _(IP6ND_PROXY_ADD_DEL, ip6nd_proxy_add_del) \ _(IP6ND_PROXY_DUMP, ip6nd_proxy_dump) \ _(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \ _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \ sw_interface_ip6_set_link_local_address) \ _(IP_CONTAINER_PROXY_ADD_DEL, ip_container_proxy_add_del) \ _(IOAM_ENABLE, ioam_enable) \ _(IOAM_DISABLE, ioam_disable) \ _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, \ ip_source_and_port_range_check_add_del) \ _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, \ ip_source_and_port_range_check_interface_add_del) \ _(IP_REASSEMBLY_SET, ip_reassembly_set) \ _(IP_REASSEMBLY_GET, ip_reassembly_get) extern void stats_dslock_with_hint (int hint, int tag); extern void stats_dsunlock (void); static void send_ip_neighbor_details (u32 sw_if_index, u8 is_ipv6, u8 is_static, u8 * mac_address, u8 * ip_address, vl_api_registration_t * reg, u32 context) { vl_api_ip_neighbor_details_t *mp; mp = vl_msg_api_alloc (sizeof (*mp)); memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_DETAILS); mp->context = context; mp->sw_if_index = htonl (sw_if_index); mp->is_ipv6 = is_ipv6; mp->is_static = is_static; memcpy (mp->mac_address, mac_address, 6); memcpy (mp->ip_address, ip_address, (is_ipv6) ? 16 : 4); vl_api_send_msg (reg, (u8 *) mp); } static void vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp) { vl_api_registration_t *reg; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; u32 sw_if_index = ntohl (mp->sw_if_index); if (mp->is_ipv6) { ip6_neighbor_t *n, *ns; ns = ip6_neighbors_entries (sw_if_index); /* *INDENT-OFF* */ vec_foreach (n, ns) { send_ip_neighbor_details (sw_if_index, mp->is_ipv6, ((n->flags & IP6_NEIGHBOR_FLAG_STATIC) ? 1 : 0), (u8 *) n->link_layer_address, (u8 *) & (n->key.ip6_address.as_u8), reg, mp->context); } /* *INDENT-ON* */ vec_free (ns); } else { ethernet_arp_ip4_entry_t *n, *ns; ns = ip4_neighbor_entries (sw_if_index); /* *INDENT-OFF* */ vec_foreach (n, ns) { send_ip_neighbor_details (sw_if_index, mp->is_ipv6, ((n->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) ? 1 : 0), (u8*) n->ethernet_address, (u8*) & (n->ip4_address.as_u8), reg, mp->context); } /* *INDENT-ON* */ vec_free (ns); } } void copy_fib_next_hop (fib_route_path_encode_t * api_rpath, void *fp_arg) { int is_ip4; vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg; if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4) fp->afi = IP46_TYPE_IP4; else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6) fp->afi = IP46_TYPE_IP6; else { is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr); if (is_ip4) fp->afi = IP46_TYPE_IP4; else fp->afi = IP46_TYPE_IP6; } if (fp->afi == IP46_TYPE_IP4) memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4, sizeof (api_rpath->rpath.frp_addr.ip4)); else memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6, sizeof (api_rpath->rpath.frp_addr.ip6)); } static void send_ip_fib_details (vpe_api_main_t * am, vl_api_registration_t * reg, const fib_table_t * table, const fib_prefix_t * pfx, fib_route_path_encode_t * api_rpaths, u32 context) { vl_api_ip_fib_details_t *mp; fib_route_path_encode_t *api_rpath; vl_api_fib_path_t *fp; int path_count; path_count = vec_len (api_rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS); mp->context = context; mp->table_id = htonl (table->ft_table_id); memcpy (mp->table_name, table->ft_desc, clib_min (vec_len (table->ft_desc), sizeof (mp->table_name))); mp->address_length = pfx->fp_len; memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4)); mp->count = htonl (path_count); fp = mp->path; vec_foreach (api_rpath, api_rpaths) { memset (fp, 0, sizeof (*fp)); switch (api_rpath->dpo.dpoi_type) { case DPO_RECEIVE: fp->is_local = true; break; case DPO_DROP: fp->is_drop = true; break; case DPO_IP_NULL: switch (api_rpath->dpo.dpoi_index) { case IP_NULL_ACTION_NONE: fp->is_drop = true; break; case IP_NULL_ACTION_SEND_ICMP_UNREACH: fp->is_unreach = true; break; case IP_NULL_ACTION_SEND_ICMP_PROHIBIT: fp->is_prohibit = true; break; default: break; } break; default: break; } fp->weight = api_rpath->rpath.frp_weight; fp->preference = api_rpath->rpath.frp_preference; fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); copy_fib_next_hop (api_rpath, fp); fp++; } vl_api_send_msg (reg, (u8 *) mp); } typedef struct vl_api_ip_fib_dump_walk_ctx_t_ { fib_node_index_t *feis; } vl_api_ip_fib_dump_walk_ctx_t; static fib_table_walk_rc_t vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg) { vl_api_ip_fib_dump_walk_ctx_t *ctx = arg; vec_add1 (ctx->feis, fei); return (FIB_TABLE_WALK_CONTINUE); } static void vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; ip4_main_t *im = &ip4_main; fib_table_t *fib_table; fib_node_index_t *lfeip; fib_prefix_t pfx; u32 fib_index; fib_route_path_encode_t *api_rpaths; vl_api_ip_fib_dump_walk_ctx_t ctx = { .feis = NULL, }; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; /* *INDENT-OFF* */ pool_foreach (fib_table, im->fibs, ({ fib_table_walk(fib_table->ft_index, FIB_PROTOCOL_IP4, vl_api_ip_fib_dump_walk, &ctx); })); /* *INDENT-ON* */ vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort); vec_foreach (lfeip, ctx.feis) { fib_entry_get_prefix (*lfeip, &pfx); fib_index = fib_entry_get_fib_index (*lfeip); fib_table = fib_table_get (fib_index, pfx.fp_proto); api_rpaths = NULL; fib_entry_encode (*lfeip, &api_rpaths); send_ip_fib_details (am, reg, fib_table, &pfx, api_rpaths, mp->context); vec_free (api_rpaths); } vec_free (ctx.feis); } static void send_ip6_fib_details (vpe_api_main_t * am, vl_api_registration_t * reg, const fib_table_t * table, const fib_prefix_t * pfx, fib_route_path_encode_t * api_rpaths, u32 context) { vl_api_ip6_fib_details_t *mp; fib_route_path_encode_t *api_rpath; vl_api_fib_path_t *fp; int path_count; path_count = vec_len (api_rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS); mp->context = context; mp->table_id = htonl (table->ft_table_id); mp->address_length = pfx->fp_len; memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6)); memcpy (mp->table_name, table->ft_desc, clib_min (vec_len (table->ft_desc), sizeof (mp->table_name))); mp->count = htonl (path_count); fp = mp->path; vec_foreach (api_rpath, api_rpaths) { memset (fp, 0, sizeof (*fp)); switch (api_rpath->dpo.dpoi_type) { case DPO_RECEIVE: fp->is_local = true; break; case DPO_DROP: fp->is_drop = true; break; case DPO_IP_NULL: switch (api_rpath->dpo.dpoi_index) { case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_NONE: fp->is_drop = true; break; case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_SEND_ICMP_UNREACH: fp->is_unreach = true; break; case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_SEND_ICMP_PROHIBIT: fp->is_prohibit = true; break; default: break; } break; default: break; } fp->weight = api_rpath->rpath.frp_weight; fp->preference = api_rpath->rpath.frp_preference; fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); copy_fib_next_hop (api_rpath, fp); fp++; } vl_api_send_msg (reg, (u8 *) mp); } typedef struct apt_ip6_fib_show_ctx_t_ { u32 fib_index; fib_node_index_t *entries; } api_ip6_fib_show_ctx_t; static void api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp, void *arg) { api_ip6_fib_show_ctx_t *ctx = arg; if ((kvp->key[2] >> 32) == ctx->fib_index) { vec_add1 (ctx->entries, kvp->value); } } static void api_ip6_fib_table_get_all (vl_api_registration_t * reg, vl_api_ip6_fib_dump_t * mp, fib_table_t * fib_table) { vpe_api_main_t *am = &vpe_api_main; ip6_main_t *im6 = &ip6_main; fib_node_index_t *fib_entry_index; api_ip6_fib_show_ctx_t ctx = { .fib_index = fib_table->ft_index, .entries = NULL, }; fib_route_path_encode_t *api_rpaths; fib_prefix_t pfx; BV (clib_bihash_foreach_key_value_pair) ((BVT (clib_bihash) *) & im6->ip6_table[IP6_FIB_TABLE_NON_FWDING]. ip6_hash, api_ip6_fib_table_put_entries, &ctx); vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort); vec_foreach (fib_entry_index, ctx.entries) { fib_entry_get_prefix (*fib_entry_index, &pfx); api_rpaths = NULL; fib_entry_encode (*fib_entry_index, &api_rpaths); send_ip6_fib_details (am, reg, fib_table, &pfx, api_rpaths, mp->context); vec_free (api_rpaths); } vec_free (ctx.entries); } static void vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp) { vl_api_registration_t *reg; ip6_main_t *im6 = &ip6_main; fib_table_t *fib_table; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; /* *INDENT-OFF* */ pool_foreach (fib_table, im6->fibs, ({ api_ip6_fib_table_get_all(reg, mp, fib_table); })); /* *INDENT-ON* */ } static void send_ip_mfib_details (vl_api_registration_t * reg, u32 context, u32 table_id, fib_node_index_t mfei) { fib_route_path_encode_t *api_rpath, *api_rpaths = NULL; vl_api_ip_mfib_details_t *mp; mfib_entry_t *mfib_entry; vl_api_fib_path_t *fp; mfib_prefix_t pfx; int path_count; mfib_entry = mfib_entry_get (mfei); mfib_entry_get_prefix (mfei, &pfx); mfib_entry_encode (mfei, &api_rpaths); path_count = vec_len (api_rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_MFIB_DETAILS); mp->context = context; mp->rpf_id = mfib_entry->mfe_rpf_id; mp->entry_flags = mfib_entry->mfe_flags; mp->table_id = htonl (table_id); mp->address_length = pfx.fp_len; memcpy (mp->grp_address, &pfx.fp_grp_addr.ip4, sizeof (pfx.fp_grp_addr.ip4)); memcpy (mp->src_address, &pfx.fp_src_addr.ip4, sizeof (pfx.fp_src_addr.ip4)); mp->count = htonl (path_count); fp = mp->path; vec_foreach (api_rpath, api_rpaths) { memset (fp, 0, sizeof (*fp)); fp->weight = 0; fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); copy_fib_next_hop (api_rpath, fp); fp++; } vec_free (api_rpaths); vl_api_send_msg (reg, (u8 *) mp); } typedef struct vl_api_ip_mfib_dump_ctc_t_ { fib_node_index_t *entries; } vl_api_ip_mfib_dump_ctc_t; static int vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg) { vl_api_ip_mfib_dump_ctc_t *ctx = arg; vec_add1 (ctx->entries, fei); return (0); } static void vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp) { vl_api_registration_t *reg; ip4_main_t *im = &ip4_main; mfib_table_t *mfib_table; fib_node_index_t *mfeip; vl_api_ip_mfib_dump_ctc_t ctx = { .entries = NULL, }; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; /* *INDENT-OFF* */ pool_foreach (mfib_table, im->mfibs, ({ ip4_mfib_table_walk(&mfib_table->v4, vl_api_ip_mfib_table_dump_walk, &ctx); vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort); vec_foreach (mfeip, ctx.entries) { send_ip_mfib_details (reg, mp->context, mfib_table->mft_table_id, *mfeip); } vec_reset_length (ctx.entries); })); /* *INDENT-ON* */ vec_free (ctx.entries); } static void send_ip6_mfib_details (vpe_api_main_t * am, vl_api_registration_t * reg, u32 table_id, mfib_prefix_t * pfx, fib_route_path_encode_t * api_rpaths, u32 context) { vl_api_ip6_mfib_details_t *mp; fib_route_path_encode_t *api_rpath; vl_api_fib_path_t *fp; int path_count; path_count = vec_len (api_rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP6_MFIB_DETAILS); mp->context = context; mp->table_id = htonl (table_id); mp->address_length = pfx->fp_len; memcpy (mp->grp_address, &pfx->fp_grp_addr.ip6, sizeof (pfx->fp_grp_addr.ip6)); memcpy (mp->src_address, &pfx->fp_src_addr.ip6, sizeof (pfx->fp_src_addr.ip6)); mp->count = htonl (path_count); fp = mp->path; vec_foreach (api_rpath, api_rpaths) { memset (fp, 0, sizeof (*fp)); fp->weight = 0; fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); copy_fib_next_hop (api_rpath, fp); fp++; } vl_api_send_msg (reg, (u8 *) mp); } typedef struct vl_api_ip6_mfib_dump_ctc_t_ { fib_node_index_t *entries; } vl_api_ip6_mfib_dump_ctc_t; static int vl_api_ip6_mfib_table_dump_walk (fib_node_index_t fei, void *arg) { vl_api_ip6_mfib_dump_ctc_t *ctx = arg; vec_add1 (ctx->entries, fei); return (0); } static void vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; ip6_main_t *im = &ip6_main; mfib_table_t *mfib_table; fib_node_index_t *mfeip; mfib_prefix_t pfx; fib_route_path_encode_t *api_rpaths = NULL; vl_api_ip6_mfib_dump_ctc_t ctx = { .entries = NULL, }; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; /* *INDENT-OFF* */ pool_foreach (mfib_table, im->mfibs, ({ ip6_mfib_table_walk(&mfib_table->v6, vl_api_ip6_mfib_table_dump_walk, &ctx); vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort); vec_foreach(mfeip, ctx.entries) { mfib_entry_get_prefix (*mfeip, &pfx); mfib_entry_encode (*mfeip, &api_rpaths); send_ip6_mfib_details (am, reg, mfib_table->mft_table_id, &pfx, api_rpaths, mp->context); } vec_reset_length (api_rpaths); vec_reset_length (ctx.entries); })); /* *INDENT-ON* */ vec_free (ctx.entries); vec_free (api_rpaths); } static void vl_api_ip_punt_police_t_handler (vl_api_ip_punt_police_t * mp, vlib_main_t * vm) { vl_api_ip_punt_police_reply_t *rmp; int rv = 0; if (mp->is_ip6) ip6_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index)); else ip4_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index)); REPLY_MACRO (VL_API_IP_PUNT_POLICE_REPLY); } static void vl_api_ip_punt_redirect_t_handler (vl_api_ip_punt_redirect_t * mp, vlib_main_t * vm) { vl_api_ip_punt_redirect_reply_t *rmp; int rv = 0; if (mp->is_add) { ip46_address_t nh; memset (&nh, 0, sizeof (nh)); if (mp->is_ip6) { memcpy (&nh.ip6, mp->nh, sizeof (nh.ip6)); ip6_punt_redirect_add (ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index), &nh); } else { memcpy (&nh.ip4, mp->nh, sizeof (nh.ip4)); ip4_punt_redirect_add (ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index), &nh); } } else { if (mp->is_ip6) { ip6_punt_redirect_del (ntohl (mp->rx_sw_if_index)); } else { ip4_punt_redirect_del (ntohl (mp->rx_sw_if_index)); } } REPLY_MACRO (VL_API_IP_PUNT_REDIRECT_REPLY); } static void vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, vlib_main_t * vm) { vl_api_ip_neighbor_add_del_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); int rv = 0; VALIDATE_SW_IF_INDEX (mp); stats_dslock_with_hint (1 /* release hint */ , 7 /* tag */ ); /* * there's no validation here of the ND/ARP entry being added. * The expectation is that the FIB will ensure that nothing bad * will come of adding bogus entries. */ if (mp->is_ipv6) { if (mp->is_add) rv = vnet_set_ip6_ethernet_neighbor (vm, ntohl (mp->sw_if_index), (ip6_address_t *) (mp->dst_address), mp->mac_address, sizeof (mp->mac_address), mp->is_static, mp->is_no_adj_fib); else rv = vnet_unset_ip6_ethernet_neighbor (vm, ntohl (mp->sw_if_index), (ip6_address_t *) (mp->dst_address), mp->mac_address, sizeof (mp->mac_address)); } else { ethernet_arp_ip4_over_ethernet_address_t a; clib_memcpy (&a.ethernet, mp->mac_address, 6); clib_memcpy (&a.ip4, mp->dst_address, 4); if (mp->is_add) rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a, mp->is_static, mp->is_no_adj_fib); else rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a); } stats_dsunlock (); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY); } void ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api) { u32 fib_index, mfib_index; /* * ignore action on the default table - this is always present * and cannot be added nor deleted from the API */ if (0 != table_id) { /* * The API holds only one lock on the table. * i.e. it can be added many times via the API but needs to be * deleted only once. * The FIB index for unicast and multicast is not necessarily the * same, since internal VPP systesm (like LISP and SR) create * their own unicast tables. */ fib_index = fib_table_find (fproto, table_id); mfib_index = mfib_table_find (fproto, table_id); if (~0 != fib_index) { fib_table_unlock (fib_index, fproto, (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI)); } if (~0 != mfib_index) { mfib_table_unlock (mfib_index, fproto, (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI)); } } } void vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp) { vl_api_ip_table_add_del_reply_t *rmp; fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); u32 table_id = ntohl (mp->table_id); int rv = 0; if (mp->is_add) { ip_table_create (fproto, table_id, 1, mp->name); } else { ip_table_delete (fproto, table_id, 1); } REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY); } int add_del_route_t_handler (u8 is_multipath, u8 is_add, u8 is_drop, u8 is_unreach, u8 is_prohibit, u8 is_local, u8 is_multicast, u8 is_classify, u32 classify_table_index, u8 is_resolve_host, u8 is_resolve_attached, u8 is_interface_rx, u8 is_rpf_id, u8 is_dvr, u8 is_source_lookup, u8 is_udp_encap, u32 fib_index, const fib_prefix_t * prefix, dpo_proto_t next_hop_proto, const ip46_address_t * next_hop, u32 next_hop_id, u32 next_hop_sw_if_index, u8 next_hop_fib_index, u16 next_hop_weight, u16 next_hop_preference, mpls_label_t next_hop_via_label, mpls_label_t * next_hop_out_label_stack) { vnet_classify_main_t *cm = &vnet_classify_main; fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE; fib_route_path_t path = { .frp_proto = next_hop_proto, .frp_addr = (NULL == next_hop ? zero_addr : *next_hop), .frp_sw_if_index = next_hop_sw_if_index, .frp_fib_index = next_hop_fib_index, .frp_weight = next_hop_weight, .frp_preference = next_hop_preference, .frp_label_stack = next_hop_out_label_stack, }; fib_route_path_t *paths = NULL; fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE; /* * the special INVALID label meams we are not recursing via a * label. Exp-null value is never a valid via-label so that * also means it's not a via-label and means clients that set * it to 0 by default get the expected behaviour */ if ((MPLS_LABEL_INVALID != next_hop_via_label) && (0 != next_hop_via_label)) { path.frp_proto = DPO_PROTO_MPLS; path.frp_local_label = next_hop_via_label; path.frp_eos = MPLS_NON_EOS; } if (is_dvr) path_flags |= FIB_ROUTE_PATH_DVR; if (is_resolve_host) path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST; if (is_resolve_attached) path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; if (is_interface_rx) path_flags |= FIB_ROUTE_PATH_INTF_RX; if (is_rpf_id) path_flags |= FIB_ROUTE_PATH_RPF_ID; if (is_source_lookup) path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP; if (is_multicast) entry_flags |= FIB_ENTRY_FLAG_MULTICAST; if (is_udp_encap) { path_flags |= FIB_ROUTE_PATH_UDP_ENCAP; path.frp_udp_encap_id = next_hop_id; } if (path.frp_sw_if_index == ~0 && ip46_address_is_zero (&path.frp_addr) && path.frp_fib_index != ~0) { path_flags |= FIB_ROUTE_PATH_DEAG; } path.frp_flags = path_flags; if (is_multipath) { stats_dslock_with_hint (1 /* release hint */ , 10 /* tag */ ); vec_add1 (paths, path); if (is_add) fib_table_entry_path_add2 (fib_index, prefix, FIB_SOURCE_API, entry_flags, paths); else fib_table_entry_path_remove2 (fib_index, prefix, FIB_SOURCE_API, paths); vec_free (paths); stats_dsunlock (); return 0; } stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ ); if (is_drop || is_local || is_classify || is_unreach || is_prohibit) { /* * special route types that link directly to the adj */ if (is_add) { dpo_id_t dpo = DPO_INVALID; dpo_proto_t dproto; dproto = fib_proto_to_dpo (prefix->fp_proto); if (is_drop) ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo); else if (is_local) receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo); else if (is_unreach) ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo); else if (is_prohibit) ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_SEND_ICMP_PROHIBIT, &dpo); else if (is_classify) { if (pool_is_free_index (cm->tables, ntohl (classify_table_index))) { stats_dsunlock (); return VNET_API_ERROR_NO_SUCH_TABLE; } dpo_set (&dpo, DPO_CLASSIFY, dproto, classify_dpo_create (dproto, ntohl (classify_table_index))); } else { stats_dsunlock (); return VNET_API_ERROR_NO_SUCH_TABLE; } fib_table_entry_special_dpo_update (fib_index, prefix, FIB_SOURCE_API, FIB_ENTRY_FLAG_EXCLUSIVE, &dpo); dpo_reset (&dpo); } else { fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API); } } else { if (is_add) { vec_add1 (paths, path); fib_table_entry_update (fib_index, prefix, FIB_SOURCE_API, entry_flags, paths); vec_free (paths); } else { fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API); } } stats_dsunlock (); return (0); } int add_del_route_check (fib_protocol_t table_proto, u32 table_id, u32 next_hop_sw_if_index, dpo_proto_t next_hop_table_proto, u32 next_hop_table_id, u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index) { vnet_main_t *vnm = vnet_get_main (); *fib_index = fib_table_find (table_proto, ntohl (table_id)); if (~0 == *fib_index) { /* No such VRF, and we weren't asked to create one */ return VNET_API_ERROR_NO_SUCH_FIB; } if (!is_rpf_id && ~0 != ntohl (next_hop_sw_if_index)) { if (pool_is_free_index (vnm->interface_main.sw_interfaces, ntohl (next_hop_sw_if_index))) { return VNET_API_ERROR_NO_MATCHING_INTERFACE; } } else { fib_protocol_t fib_nh_proto; if (next_hop_table_proto > DPO_PROTO_MPLS) return (0); fib_nh_proto = dpo_proto_to_fib (next_hop_table_proto); if (is_rpf_id) *next_hop_fib_index = mfib_table_find (fib_nh_proto, ntohl (next_hop_table_id)); else *next_hop_fib_index = fib_table_find (fib_nh_proto, ntohl (next_hop_table_id)); if (~0 == *next_hop_fib_index) { /* No such VRF, and we weren't asked to create one */ return VNET_API_ERROR_NO_SUCH_FIB; } } return (0); } static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) { u32 fib_index, next_hop_fib_index; mpls_label_t *label_stack = NULL; int rv, ii, n_labels;; rv = add_del_route_check (FIB_PROTOCOL_IP4, mp->table_id, mp->next_hop_sw_if_index, DPO_PROTO_IP4, mp->next_hop_table_id, 0, &fib_index, &next_hop_fib_index); if (0 != rv) return (rv); fib_prefix_t pfx = { .fp_len = mp->dst_address_length, .fp_proto = FIB_PROTOCOL_IP4, }; clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4)); ip46_address_t nh; memset (&nh, 0, sizeof (nh)); memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4)); n_labels = mp->next_hop_n_out_labels; if (n_labels == 0) ; else if (1 == n_labels) vec_add1 (label_stack, ntohl (mp->next_hop_out_label_stack[0])); else { vec_validate (label_stack, n_labels - 1); for (ii = 0; ii < n_labels; ii++) label_stack[ii] = ntohl (mp->next_hop_out_label_stack[ii]); } return (add_del_route_t_handler (mp->is_multipath, mp->is_add, mp->is_drop, mp->is_unreach, mp->is_prohibit, mp->is_local, 0, mp->is_classify,
/*
 * ip/ports.def: tcp/udp port definitions
 *
 * Eliot Dresselhaus
 * August, 2005
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
PORT NUMBERS

(last updated 18 October 2005) 

The port numbers are divided into three ranges: the Well Known Ports,
the Registered Ports, and the Dynamic and/or Private Ports.

The Well Known Ports are those from 0 through 1023.

The Registered Ports are those from 1024 through 49151

The Dynamic and/or Private Ports are those from 49152 through 65535


************************************************************************
* PLEASE NOTE THE FOLLOWING:                                           *
*                                                                      *
* 1. UNASSIGNED PORT NUMBERS SHOULD NOT BE USED.  THE IANA WILL ASSIGN *
* THE NUMBER FOR THE PORT AFTER YOUR APPLICATION HAS BEEN APPROVED.    *
*                                                                      *
* 2. ASSIGNMENT OF A PORT NUMBER DOES NOT IN ANY WAY IMPLY AN          *
* ENDORSEMENT OF AN APPLICATION OR PRODUCT, AND THE FACT THAT NETWORK  *
* TRAFFIC IS FLOWING TO OR FROM A REGISTERED PORT DOES NOT MEAN THAT   *
* IT IS "GOOD" TRAFFIC. FIREWALL AND SYSTEM ADMINISTRATORS SHOULD      *
* CHOOSE HOW TO CONFIGURE THEIR SYSTEMS BASED ON THEIR KNOWLEDGE OF    *
* THE TRAFFIC IN QUESTION, NOT WHETHER THERE IS A PORT NUMBER          *
* REGISTERED OR NOT.                                                   *
************************************************************************


WELL KNOWN PORT NUMBERS

The Well Known Ports are assigned by the IANA and on most systems can
only be used by system (or root) processes or by programs executed by
privileged users.

Ports are used in the TCP [RFC793] to name the ends of logical
connections which carry long term conversations.  For the purpose of
providing services to unknown callers, a service contact port is
defined.  This list specifies the port used by the server process as
its contact port.  The contact port is sometimes called the
"well-known port".

To the extent possible, these same port assignments are used with the
UDP [RFC768].

The range for assigned ports managed by the IANA is 0-1023.
*/
ip_port (TCPMUX, 1)
ip_port (COMPRESS_NET_MANAGEMENT, 2)
ip_port (COMPRESS_NET, 3)
ip_port (RJE, 5)
ip_port (ECHO, 7)
ip_port (DISCARD, 9)
ip_port (SYSTAT, 11)
ip_port (DAYTIME, 13)
ip_port (QOTD, 17)
ip_port (MSP, 18)
ip_port (CHARGEN, 19)
ip_port (FTP_DATA, 20)
ip_port (FTP, 21)
ip_port (SSH, 22)
ip_port (TELNET, 23)
ip_port (SMTP, 25)
ip_port (NSW_FE, 27)
ip_port (MSG_ICP, 29)
ip_port (MSG_AUTH, 31)
ip_port (DSP, 33)
ip_port (TIME, 37)
ip_port (RAP, 38)
ip_port (RLP, 39)
ip_port (GRAPHICS, 41)
ip_port (NAME, 42)
ip_port (NAMESERVER, 42)
ip_port (NICNAME, 43)
ip_port (MPM_FLAGS, 44)
ip_port (MPM, 45)
ip_port (MPM_SND, 46)
ip_port (NI_FTP, 47)
ip_port (AUDITD, 48)
ip_port (TACACS, 49)
ip_port (RE_MAIL_CK, 50)
ip_port (LA_MAINT, 51)
ip_port (XNS_TIME, 52)
ip_port (DNS, 53)
ip_port (XNS_CH, 54)
ip_port (ISI_GL, 55)
ip_port (XNS_AUTH, 56)
ip_port (XNS_MAIL, 58)
ip_port (NI_MAIL, 61)
ip_port (ACAS, 62)
ip_port (WHOIS_PLUS_PLUS, 63)
ip_port (COVIA, 64)
ip_port (TACACS_DS, 65)
ip_port (ORACLE_SQL_NET, 66)
ip_port (BOOTPS, 67)
ip_port (BOOTPC, 68)
ip_port (TFTP, 69)
ip_port (GOPHER, 70)
ip_port (NETRJS_1, 71)
ip_port (NETRJS_2, 72)
ip_port (NETRJS_3, 73)
ip_port (NETRJS_4, 74)
ip_port (DEOS, 76)
ip_port (VETTCP, 78)
ip_port (FINGER, 79)
ip_port (WWW, 80)
ip_port (HOSTS2_NS, 81)
ip_port (XFER, 82)
ip_port (MIT_ML_DEV, 83)
ip_port (CTF, 84)
ip_port (MIT_ML_DEV1, 85)
ip_port (MFCOBOL, 86)
ip_port (KERBEROS, 88)
ip_port (SU_MIT_TG, 89)
ip_port (DNSIX, 90)
ip_port (MIT_DOV, 91)
ip_port (NPP, 92)
ip_port (DCP, 93)
ip_port (OBJCALL, 94)
ip_port (SUPDUP, 95)
ip_port (DIXIE, 96)
ip_port (SWIFT_RVF, 97)
ip_port (TACNEWS, 98)
ip_port (METAGRAM, 99)
ip_port (NEWACCT, 100)
ip_port (HOSTNAME, 101)
ip_port (ISO_TSAP, 102)
ip_port (GPPITNP, 103)
ip_port (ACR_NEMA, 104)
ip_port (CSO, 105)
ip_port (CSNET_NS, 105)
ip_port (3COM_TSMUX, 106)
ip_port (RTELNET, 107)
ip_port (SNAGAS, 108)
ip_port (POP2, 109)
ip_port (POP3, 110)
ip_port (SUNRPC, 111)
ip_port (MCIDAS, 112)
ip_port (IDENT, 113)
ip_port (SFTP, 115)
ip_port (ANSANOTIFY, 116)
ip_port (UUCP_PATH, 117)
ip_port (SQLSERV, 118)
ip_port (NNTP, 119)
ip_port (CFDPTKT, 120)
ip_port (ERPC, 121)
ip_port (SMAKYNET, 122)
ip_port (NTP, 123)
ip_port (ANSATRADER, 124)
ip_port (LOCUS_MAP, 125)
ip_port (NXEDIT, 126)
ip_port (LOCUS_CON, 127)
ip_port (GSS_XLICEN, 128)
ip_port (PWDGEN, 129)
ip_port (CISCO_FNA, 130)
ip_port (CISCO_TNA, 131)
ip_port (CISCO_SYS, 132)
ip_port (STATSRV, 133)
ip_port (INGRES_NET, 134)
ip_port (EPMAP, 135)
ip_port (PROFILE, 136)
ip_port (NETBIOS_NS, 137)
ip_port (NETBIOS_DGM, 138)
ip_port (NETBIOS_SSN, 139)
ip_port (EMFIS_DATA, 140)
ip_port (EMFIS_CNTL, 141)
ip_port (BL_IDM, 142)
ip_port (IMAP, 143)
ip_port (UMA, 144)
ip_port (UAAC, 145)
ip_port (ISO_TP0, 146)
ip_port (ISO_IP, 147)
ip_port (JARGON, 148)
ip_port (AED_512, 149)
ip_port (SQL_NET, 150)
ip_port (HEMS, 151)
ip_port (BFTP, 152)
ip_port (SGMP, 153)
ip_port (NETSC_PROD, 154)
ip_port (NETSC_DEV, 155)
ip_port (SQLSRV, 156)
ip_port (KNET_CMP, 157)
ip_port (PCMAIL_SRV, 158)
ip_port (NSS_ROUTING, 159)
ip_port (SGMP_TRAPS, 160)
ip_port (SNMP, 161)
ip_port (SNMPTRAP, 162)
ip_port (CMIP_MAN, 163)
ip_port (CMIP_AGENT, 164)
ip_port (XNS_COURIER, 165)
ip_port (S_NET, 166)
ip_port (NAMP, 167)
ip_port (RSVD, 168)
ip_port (SEND, 169)
ip_port (PRINT_SRV, 170)
ip_port (MULTIPLEX, 171)
ip_port (CL1, 172)
ip_port (XYPLEX_MUX, 173)
ip_port (MAILQ, 174)
ip_port (VMNET, 175)
ip_port (GENRAD_MUX, 176)
ip_port (XDMCP, 177)
ip_port (NEXTSTEP, 178)
ip_port (BGP, 179)
ip_port (RIS, 180)
ip_port (UNIFY, 181)
ip_port (AUDIT, 182)
ip_port (OCBINDER, 183)
ip_port (OCSERVER, 184)
ip_port (REMOTE_KIS, 185)
ip_port (KIS, 186)
ip_port (ACI, 187)
ip_port (MUMPS, 188)
ip_port (QFT, 189)
ip_port (GACP, 190)
ip_port (PROSPERO, 191)
ip_port (OSU_NMS, 192)
ip_port (SRMP, 193)
ip_port (IRC, 194)
ip_port (DN6_NLM_AUD, 195)
ip_port (DN6_SMM_RED, 196)
ip_port (DLS, 197)
ip_port (DLS_MON, 198)
ip_port (SMUX, 199)
ip_port (SRC, 200)
ip_port (AT_RTMP, 201)
ip_port (AT_NBP, 202)
ip_port (AT_3, 203)
ip_port (AT_ECHO, 204)
ip_port (AT_5, 205)
ip_port (AT_ZIS, 206)
ip_port (AT_7, 207)
ip_port (AT_8, 208)
ip_port (QMTP, 209)
ip_port (Z39_50, 210)
ip_port (TI914CG, 211)
ip_port (ANET, 212)
ip_port (IPX, 213)
ip_port (VMPWSCS, 214)
ip_port (SOFTPC, 215)
ip_port (CAILIC, 216)
ip_port (DBASE, 217)
ip_port (MPP, 218)
ip_port (UARPS, 219)
ip_port (IMAP3, 220)
ip_port (FLN_SPX, 221)
ip_port (RSH_SPX, 222)
ip_port