Date: Sat, 16 Sep 2017 16:24:39 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r323646 - projects/bsd_rdma_4_9/sys/ofed/drivers/infiniband/core Message-ID: <201709161624.v8GGOdS8047118@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hselasky Date: Sat Sep 16 16:24:38 2017 New Revision: 323646 URL: https://svnweb.freebsd.org/changeset/base/323646 Log: Improve ibcore address resolving: - Add more sanity checks. - Preserve source port number when resolving address. - Remove no longer needed scope ID hacks for IPv6. Sponsored by: Mellanox Technologies Modified: projects/bsd_rdma_4_9/sys/ofed/drivers/infiniband/core/ib_addr.c Modified: projects/bsd_rdma_4_9/sys/ofed/drivers/infiniband/core/ib_addr.c ============================================================================== --- projects/bsd_rdma_4_9/sys/ofed/drivers/infiniband/core/ib_addr.c Sat Sep 16 16:23:00 2017 (r323645) +++ projects/bsd_rdma_4_9/sys/ofed/drivers/infiniband/core/ib_addr.c Sat Sep 16 16:24:38 2017 (r323646) @@ -162,15 +162,10 @@ int rdma_translate_ip(const struct sockaddr *addr, break; #endif #ifdef INET6 - case AF_INET6: { - struct in6_addr in6_addr = ((const struct sockaddr_in6 *)addr)->sin6_addr; - - /* embed scope ID */ - in6_addr.s6_addr[3] = ((const struct sockaddr_in6 *)addr)->sin6_scope_id; - - dev = ip6_dev_find(dev_addr->net, in6_addr); + case AF_INET6: + dev = ip6_dev_find(dev_addr->net, + ((const struct sockaddr_in6 *)addr)->sin6_addr); break; - } #endif default: break; @@ -245,67 +240,90 @@ static int addr4_resolve(struct sockaddr_in *src_in, { struct sockaddr_in dst_tmp = *dst_in; u8 edst[MAX_ADDR_LEN]; + in_port_t src_port; + struct sockaddr *saddr; struct rtentry *rte; struct ifnet *ifp; int error; + int type; - /* - * Make sure the socket address length field - * is set, else rtalloc1() will fail. - */ - dst_tmp.sin_len = sizeof(dst_tmp); - + /* set VNET, if any */ CURVNET_SET(addr->net); + /* set default TTL limit */ addr->hoplimit = V_ip_defttl; - /* lookup route for destination */ - rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0); - CURVNET_RESTORE(); + type = 0; + if (src_in->sin_addr.s_addr == INADDR_ANY) + type |= 1; + if (dst_tmp.sin_addr.s_addr == INADDR_ANY) + type |= 2; /* - * Make sure the route exists and has a valid link. + * Make sure the socket address length field + * is set, else rtalloc1() will fail. */ - if (rte == NULL) { - error = EHOSTUNREACH; - goto done; - } else if (rte->rt_ifp == NULL || RT_LINK_IS_UP(rte->rt_ifp) == 0) { - RTFREE_LOCKED(rte); - error = EHOSTUNREACH; - goto done; - } else if (src_in->sin_addr.s_addr != INADDR_ANY) { + dst_tmp.sin_len = sizeof(dst_tmp); + + /* Step 1 - lookup destination route if any */ + switch (type) { + case 0: + case 1: + /* regular destination route lookup */ + rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0); + if (rte == NULL) { + error = EHOSTUNREACH; + goto done; + } else if (rte->rt_ifp == NULL || rte->rt_ifp == V_loif || + RT_LINK_IS_UP(rte->rt_ifp) == 0) { + RTFREE_LOCKED(rte); + error = EHOSTUNREACH; + goto done; + } RT_UNLOCK(rte); + break; + default: + error = ENETUNREACH; + goto done; + } + /* Step 2 - find outgoing network interface */ + switch (type) { + case 0: + /* source check */ ifp = ip_dev_find(addr->net, src_in->sin_addr.s_addr); if (ifp == NULL) { - RTFREE(rte); error = ENETUNREACH; - goto done; + goto error_rt_free; } else if (ifp != rte->rt_ifp) { error = ENETUNREACH; - goto failure; + goto error_put_ifp; } - } else { - struct sockaddr *saddr; - + break; + case 1: + /* get destination network interface from route */ ifp = rte->rt_ifp; dev_hold(ifp); - saddr = rte->rt_ifa->ifa_addr; + + src_port = src_in->sin_port; memcpy(src_in, saddr, rdma_addr_size(saddr)); - RT_UNLOCK(rte); + src_in->sin_port = src_port; /* preserve port number */ + break; + default: + break; } /* - * Resolve destination MAC address + * Step 3 - resolve destination MAC address */ if (dst_tmp.sin_addr.s_addr == INADDR_BROADCAST) { rdma_copy_addr_sub(edst, ifp->if_broadcastaddr, - ifp->if_addrlen, MAX_ADDR_LEN); + ifp->if_addrlen, MAX_ADDR_LEN); } else if (IN_MULTICAST(ntohl(dst_tmp.sin_addr.s_addr))) { error = addr_resolve_multi(edst, ifp, (struct sockaddr *)&dst_tmp); if (error != 0) - goto failure; + goto error_put_ifp; } else { bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0; memset(edst, 0, sizeof(edst)); @@ -313,26 +331,34 @@ static int addr4_resolve(struct sockaddr_in *src_in, rte->rt_gateway : (const struct sockaddr *)&dst_tmp, edst, NULL, NULL); if (error != 0) - goto failure; + goto error_put_ifp; else if (is_gw != 0) addr->network = RDMA_NETWORK_IPV4; } /* - * Copy destination and source MAC addresses + * Step 4 - copy destination and source MAC addresses */ error = -rdma_copy_addr(addr, ifp, edst); - if (error != 0) { -failure: - dev_put(ifp); + if (error != 0) + goto error_put_ifp; - if (error == EWOULDBLOCK || error == EAGAIN) - error = ENODATA; - } else { - *ifpp = ifp; - } + if (rte != NULL) + RTFREE(rte); + + *ifpp = ifp; + + goto done; + +error_put_ifp: + dev_put(ifp); +error_rt_free: RTFREE(rte); done: + CURVNET_RESTORE(); + + if (error == EWOULDBLOCK || error == EAGAIN) + error = ENODATA; return (-error); } #else @@ -353,67 +379,95 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, { struct sockaddr_in6 dst_tmp = *dst_in; u8 edst[MAX_ADDR_LEN]; + in_port_t src_port; + struct sockaddr *saddr; struct rtentry *rte; struct ifnet *ifp; int error; + int type; - sa6_embedscope(&dst_tmp, 0); - sa6_embedscope(src_in, 0); - - /* - * Make sure the socket address length field - * is set, else rtalloc1() will fail. - */ - dst_tmp.sin6_len = sizeof(dst_tmp); - + /* set VNET, if any */ CURVNET_SET(addr->net); + /* set default TTL limit */ addr->hoplimit = V_ip_defttl; - /* lookup route for destination */ - rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0); - CURVNET_RESTORE(); + type = 0; + if (ipv6_addr_any(&src_in->sin6_addr)) + type |= 1; + if (ipv6_addr_any(&dst_tmp.sin6_addr)) + type |= 2; /* - * Make sure the route exists and has a valid link. + * Make sure the socket address length field + * is set, else rtalloc1() will fail. */ - if (rte == NULL) { - error = EHOSTUNREACH; - goto done; - } else if (rte->rt_ifp == NULL || RT_LINK_IS_UP(rte->rt_ifp) == 0) { - RTFREE_LOCKED(rte); - error = EHOSTUNREACH; - goto done; - } else if (!IN6_IS_ADDR_UNSPECIFIED(&src_in->sin6_addr)) { + dst_tmp.sin6_len = sizeof(dst_tmp); + + /* Step 1 - lookup destination route if any */ + switch (type) { + case 0: + /* sanity check for IPv4 addresses */ + if (ipv6_addr_v4mapped(&src_in->sin6_addr) != + ipv6_addr_v4mapped(&dst_tmp.sin6_addr)) { + error = EAFNOSUPPORT; + goto done; + } + /* FALLTHROUGH */ + case 1: + /* regular destination route lookup */ + rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0); + if (rte == NULL) { + error = EHOSTUNREACH; + goto done; + } else if (rte->rt_ifp == NULL || rte->rt_ifp == V_loif || + RT_LINK_IS_UP(rte->rt_ifp) == 0) { + RTFREE_LOCKED(rte); + error = EHOSTUNREACH; + goto done; + } RT_UNLOCK(rte); + break; + default: + error = ENETUNREACH; + goto done; + } + /* Step 2 - find outgoing network interface */ + switch (type) { + case 0: + /* source check */ ifp = ip6_dev_find(addr->net, src_in->sin6_addr); if (ifp == NULL) { - RTFREE(rte); error = ENETUNREACH; - goto done; + goto error_rt_free; } else if (ifp != rte->rt_ifp) { error = ENETUNREACH; - goto failure; + goto error_put_ifp; } - } else { - struct sockaddr *saddr; - + break; + case 1: + /* get destination network interface from route */ ifp = rte->rt_ifp; dev_hold(ifp); - saddr = rte->rt_ifa->ifa_addr; + + src_port = src_in->sin6_port; memcpy(src_in, saddr, rdma_addr_size(saddr)); - RT_UNLOCK(rte); + src_in->sin6_port = src_port; /* preserve port number */ + break; + default: + break; } /* - * Resolve destination MAC address + * Step 3 - resolve destination MAC address */ if (IN6_IS_ADDR_MULTICAST(&dst_tmp.sin6_addr)) { - error = addr_resolve_multi(edst, ifp, (struct sockaddr *)&dst_tmp); + error = addr_resolve_multi(edst, ifp, + (struct sockaddr *)&dst_tmp); if (error != 0) - goto failure; + goto error_put_ifp; } else { bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0; memset(edst, 0, sizeof(edst)); @@ -421,29 +475,34 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, rte->rt_gateway : (const struct sockaddr *)&dst_tmp, edst, NULL, NULL); if (error != 0) - goto failure; + goto error_put_ifp; else if (is_gw != 0) addr->network = RDMA_NETWORK_IPV6; } /* - * Copy destination and source MAC addresses + * Step 4 - copy destination and source MAC addresses */ error = -rdma_copy_addr(addr, ifp, edst); - if (error != 0) { -failure: - dev_put(ifp); + if (error != 0) + goto error_put_ifp; - if (error == EWOULDBLOCK || error == EAGAIN) - error = ENODATA; - } else { - *ifpp = ifp; - } + if (rte != NULL) + RTFREE(rte); + + *ifpp = ifp; + + goto done; + +error_put_ifp: + dev_put(ifp); +error_rt_free: RTFREE(rte); done: - sa6_recoverscope(&dst_tmp); - sa6_recoverscope(src_in); + CURVNET_RESTORE(); + if (error == EWOULDBLOCK || error == EAGAIN) + error = ENODATA; return (-error); } #else
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201709161624.v8GGOdS8047118>