static int cicpos_mact_open_rsop(ci_private_t *priv, void *unused) { if (priv->thr == NULL) return -EINVAL; return cicpos_mact_open(CICP_HANDLE(&priv->thr->netif)) ? 0 : -EBUSY; }
static int cicpos_mac_purge_unseen_rsop(ci_private_t *priv, void *unused) { if (priv->thr == NULL) return -EINVAL; cicpos_mac_purge_unseen(CICP_HANDLE(&priv->thr->netif)); return 0; }
static int cicpos_llap_delete_rsop(ci_private_t *priv, void *p_ifindex) { if (priv->thr == NULL) return -EINVAL; cicpos_llap_delete(CICP_HANDLE(&priv->thr->netif), *(ci_ifid_t *)p_ifindex); return 0; }
static int cicp_llap_find_rsop(ci_private_t *priv, void *arg) { cp_llap_find_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicp_llap_find(CICP_HANDLE(&priv->thr->netif), &op->ifindex_out, op->hwport, op->vlan_id); }
static int cicp_ipif_by_ifindex_rsop(ci_private_t *priv, void *arg) { cp_ipif_by_ifindex_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicp_ipif_by_ifindex(CICP_HANDLE(&priv->thr->netif), op->ifindex, &op->out_addr); }
static int cicpos_mac_row_seen_rsop(ci_private_t *priv, void *op) { if (priv->thr == NULL) return -EINVAL; cicpos_mac_row_seen(CICP_HANDLE(&priv->thr->netif), (cicp_mib_verinfo_t *)op); return 0; }
static int cicp_ipif_addr_kind_rsop(ci_private_t *priv, void *arg) { cp_ipif_addr_kind_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicp_ipif_addr_kind(CICP_HANDLE(&priv->thr->netif), op->ip_be32, &op->addr_kind); }
static int cicp_llap_retrieve_rsop(ci_private_t *priv, void *arg) { cp_llap_retrieve_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicp_llap_retrieve(CICP_HANDLE(&priv->thr->netif), op->ifindex, &op->mtu, &op->hwport, &op->mac, &op->encap, &op->base_ifindex, &op->bond_rowid); }
static int cicpos_ipif_delete_rsop(ci_private_t *priv, void *arg) { cp_ipif_delete_t *op = arg; if (priv->thr == NULL) return -EINVAL; cicpos_ipif_delete(CICP_HANDLE(&priv->thr->netif), op->ifindex, op->net_ip, op->net_ipset); return 0; }
static int cicpos_ipif_import_rsop(ci_private_t *priv, void *arg) { cp_ipif_import_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicpos_ipif_import(CICP_HANDLE(&priv->thr->netif), &op->rowid, op->ifindex, op->net_ip, op->net_ipset, op->net_bcast, op->scope); }
static int cicpos_hwport_update_rsop(ci_private_t *priv, void *arg) { cp_hwport_update_t *op = arg; if (priv->thr == NULL) return -EINVAL; cicpos_hwport_update(CICP_HANDLE(&priv->thr->netif), op->hwport, op->max_mtu); return 0; }
static int cicp_llap_import_rsop(ci_private_t *priv, void *arg) { cp_llap_import_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicp_llap_import(CICP_HANDLE(&priv->thr->netif), &op->rowid_out, op->ifindex, op->max_mtu, op->up, op->name, &op->mac); }
static int cicp_ipif_pktinfo_query_rsop(ci_private_t *priv, void *arg) { cp_ipif_pktinfo_query_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicp_ipif_pktinfo_query(CICP_HANDLE(&priv->thr->netif), &priv->thr->netif, op->pktid, op->ifindex, &op->out_spec_addr); }
static int cicpos_route_delete_rsop(ci_private_t *priv, void *arg) { cp_route_delete_t *op = arg; if (priv->thr == NULL) return -EINVAL; cicpos_route_delete(CICP_HANDLE(&priv->thr->netif), op->dest_ip, op->dest_ipset, CI_IFID_BAD); return 0; }
static int cicp_user_find_home_rsop(ci_private_t *priv, void *arg) { cp_src_addr_checks_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicp_user_find_home(CICP_HANDLE(&priv->thr->netif), &op->ip_be32, &op->hwport, &op->ifindex, &op->mac, &op->mtu, &op->encap); }
static int cicp_route_import_rsop(ci_private_t *priv, void *arg) { cp_route_import_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicp_route_import(CICP_HANDLE(&priv->thr->netif), &op->rowid, op->dest_ip, op->dest_ipset, op->next_hop_ip, op->tos, op->metric, op->pref_source, op->ifindex, op->mtu); }
static int cicpos_ipif_readrow_rsop(ci_private_t *priv, void *arg) { cp_ipif_readrow_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicpos_ipif_readrow(CICP_HANDLE(&priv->thr->netif), op->rowinfo_index, &op->table_version, &op->ifindex, &op->net_ip, &op->net_ipset, &op->net_bcast); }
static int cicpos_mac_set_rsop(ci_private_t *priv, void *arg) { cp_mac_set_t *op = arg; if (priv->thr == NULL) return -EINVAL; return cicpos_mac_set(CICP_HANDLE(&priv->thr->netif), &op->rowinfo, op->ifindex, op->ip_be32, (const ci_mac_addr_t *)op->mac, CI_USER_PTR_GET(op->os_sync_ptr)); }
/** * Put an IP_PKTINFO control message into msg ancillary data buffer. */ static void ip_cmsg_recv_pktinfo(ci_netif* netif, const ci_ip_pkt_fmt* pkt, struct cmsg_state *cmsg_state) { /* TODO: This is horribly inefficient -- two system calls. Could be made * cheap with a user-level llap table. */ struct in_pktinfo info; ci_uint32 addr; int hwport; addr = oo_ip_hdr_const(pkt)->ip_daddr_be32; info.ipi_addr.s_addr = addr; /* Set the ifindex the pkt was received at. */ { ci_ifid_t ifindex = 0; int rc = 0; hwport = netif->state->intf_i_to_hwport[pkt->intf_i]; rc = cicp_llap_find(CICP_HANDLE(netif), &ifindex, CI_HWPORT_ID(hwport), pkt->vlan); if( rc != 0 ) LOG_E(ci_log("%s: cicp_llap_find(intf_i=%d, hwport=%d) failed rc=%d", __FUNCTION__, pkt->intf_i, hwport, rc)); info.ipi_ifindex = ifindex; } /* RFC1122: The specific-destination address is defined to be the * destination address in the IP header unless the header contains a * broadcast or multicast address, in which case the specific-destination * is an IP address assigned to the physical interface on which the * datagram arrived. */ /*\ FIXME: we should drop the packet if this call fails */ cicp_ipif_pktinfo_query(CICP_HANDLE(netif), netif, OO_PKT_P(pkt), info.ipi_ifindex, &info.ipi_spec_dst.s_addr ); ci_put_cmsg(cmsg_state, IPPROTO_IP, IP_PKTINFO, sizeof(info), &info); }
/*! Perform system bind on the OS backing socket. * \param ep Endpoint context * \param fd Callers FD * \param ip_addr_be32 Local address to which to bind * \param port_be16 [in] requested port [out] assigned port * \return 0 - success & [port_be16] updated * CI_SOCKET_HANDOVER, Pass to OS, OS bound ok, (no error) * CI_SOCKET_ERROR & errno set */ ci_inline int __ci_bind(ci_netif *ni, ci_sock_cmn *s, ci_uint32 ip_addr_be32, ci_uint16* port_be16 ) { int rc; ci_uint16 user_port; /* Port number specified by user, not by OS. * See bug 4015 for details */ union ci_sockaddr_u sa_u; ci_assert(s->domain == AF_INET || s->domain == AF_INET6); ci_assert( port_be16 ); user_port = *port_be16; #if CI_CFG_FAKE_IPV6 ci_assert(s->domain == AF_INET || s->domain == AF_INET6); if( s->domain == AF_INET ) ci_make_sockaddr(&sa_u.sin, s->domain, user_port, ip_addr_be32); else ci_make_sockaddr6(&sa_u.sin6, s->domain, user_port, ip_addr_be32); #else ci_assert(s->domain == AF_INET); ci_make_sockaddr(&sa_u.sin, s->domain, user_port, ip_addr_be32); #endif #ifdef __ci_driver__ rc = efab_tcp_helper_bind_os_sock(netif2tcp_helper_resource(ni), SC_SP(s), &sa_u.sa, sizeof(sa_u), port_be16); #else rc = ci_tcp_helper_bind_os_sock(ni, SC_SP(s), &sa_u.sa, sizeof(sa_u), port_be16); #endif /* bug1781: only do this if the earlier bind succeeded. * check if we can handle this socket */ if( rc != 0 ) return rc; if( user_port != 0 ) s->s_flags |= CI_SOCK_FLAG_PORT_BOUND; if( ip_addr_be32 != INADDR_ANY ) s->s_flags |= CI_SOCK_FLAG_ADDR_BOUND; s->s_flags &= ~CI_SOCK_FLAG_CONNECT_MUST_BIND; #ifndef __ci_driver__ /* We do not call bind() to alien address from in-kernel code */ if( ip_addr_be32 != INADDR_ANY && !cicp_user_addr_is_local_efab(CICP_HANDLE(ni), &ip_addr_be32) ) s->s_flags |= CI_SOCK_FLAG_BOUND_ALIEN; #endif return rc; }
int ci_udp_should_handover(citp_socket* ep, const struct sockaddr* addr, ci_uint16 lport) { ci_uint32 addr_be32; #if CI_CFG_FAKE_IPV6 if( ep->s->domain == AF_INET6 && ! ci_tcp_ipv6_is_ipv4(addr) ) goto handover; #endif if( (CI_BSWAP_BE16(lport) >= NI_OPTS(ep->netif).udp_port_handover_min && CI_BSWAP_BE16(lport) <= NI_OPTS(ep->netif).udp_port_handover_max) || (CI_BSWAP_BE16(lport) >= NI_OPTS(ep->netif).udp_port_handover2_min && CI_BSWAP_BE16(lport) <= NI_OPTS(ep->netif).udp_port_handover2_max) || (CI_BSWAP_BE16(lport) >= NI_OPTS(ep->netif).udp_port_handover3_min && CI_BSWAP_BE16(lport) <= NI_OPTS(ep->netif).udp_port_handover3_max) ) { LOG_UC(log(FNS_FMT "HANDOVER (%d <= %d <= %d)", FNS_PRI_ARGS(ep->netif, ep->s), NI_OPTS(ep->netif).udp_port_handover_min, CI_BSWAP_BE16(lport), NI_OPTS(ep->netif).udp_port_handover_max)); goto handover; } addr_be32 = ci_get_ip4_addr(ep->s->domain, addr); if( addr_be32 != CI_BSWAPC_BE32(INADDR_ANY) && ! cicp_user_addr_is_local_efab(CICP_HANDLE(ep->netif), &addr_be32) && ! CI_IP_IS_MULTICAST(addr_be32) ) { /* Either the bind/getsockname indicated that we need to let the OS * take this or the local address is not one of ours - so we can safely * hand-over as bind to a non-ANY addr cannot be revoked. * The filters (if any) have already been removed, so we just get out. */ goto handover; } return 0; handover: return 1; }
void ci_synchronise_clock(ci_netif *ni, struct oo_timesync* oo_ts_local) { ci_uint32 gc; struct oo_timesync *oo_ts; oo_ts = oo_timesync_state(CICP_HANDLE(ni)); /* Check if our current datapoint for clock_gettime is up to date, * and take another if not */ if( oo_ts_local->generation_count != oo_ts->generation_count ) { do { gc = oo_ts->generation_count; ci_rmb(); oo_ts_local->smoothed_ticks = oo_ts->smoothed_ticks; oo_ts_local->smoothed_ns = oo_ts->smoothed_ns; oo_ts_local->clock.tv_sec = oo_ts->clock.tv_sec; oo_ts_local->clock.tv_nsec = oo_ts->clock.tv_nsec; oo_ts_local->clock_made = oo_ts->clock_made; ci_rmb(); } while (gc & 1 || gc != oo_ts->generation_count); oo_ts_local->generation_count = gc; } }