^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This software is available to you under a choice of one of two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * licenses. You may choose to be licensed under the terms of the GNU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * General Public License (GPL) Version 2, available from the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * COPYING in the main directory of this source tree, or the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * OpenIB.org BSD license below:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Redistribution and use in source and binary forms, with or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * without modification, are permitted provided that the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * conditions are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * - Redistributions of source code must retain the above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * copyright notice, this list of conditions and the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * - Redistributions in binary form must reproduce the above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * copyright notice, this list of conditions and the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * disclaimer in the documentation and/or other materials
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * provided with the distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/jhash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/ratelimit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include "rds.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static struct rhashtable bind_hash_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const struct rhashtable_params ht_parms = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .nelem_hint = 768,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .key_len = RDS_BOUND_KEY_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .key_offset = offsetof(struct rds_sock, rs_bound_key),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .head_offset = offsetof(struct rds_sock, rs_bound_node),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .max_size = 16384,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .min_size = 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* Create a key for the bind hash table manipulation. Port is in network byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static inline void __rds_create_bind_key(u8 *key, const struct in6_addr *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) __be16 port, __u32 scope_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) memcpy(key, addr, sizeof(*addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) key += sizeof(*addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) memcpy(key, &port, sizeof(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) key += sizeof(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) memcpy(key, &scope_id, sizeof(scope_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Return the rds_sock bound at the given local address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * The rx path can race with rds_release. We notice if rds_release() has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * marked this socket and don't return a rs ref to the rx path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) __u32 scope_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u8 key[RDS_BOUND_KEY_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct rds_sock *rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) __rds_create_bind_key(key, addr, port, scope_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) rs = rhashtable_lookup(&bind_hash_table, key, ht_parms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (rs && (sock_flag(rds_rs_to_sk(rs), SOCK_DEAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) !refcount_inc_not_zero(&rds_rs_to_sk(rs)->sk_refcnt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) rs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) rdsdebug("returning rs %p for %pI6c:%u\n", rs, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ntohs(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* returns -ve errno or +ve port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int rds_add_bound(struct rds_sock *rs, const struct in6_addr *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) __be16 *port, __u32 scope_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int ret = -EADDRINUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u16 rover, last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u8 key[RDS_BOUND_KEY_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (*port != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) rover = be16_to_cpu(*port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (rover == RDS_FLAG_PROBE_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) last = rover;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) rover = max_t(u16, prandom_u32(), 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) last = rover - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (rover == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) rover++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (rover == RDS_FLAG_PROBE_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) __rds_create_bind_key(key, addr, cpu_to_be16(rover),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) scope_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (rhashtable_lookup_fast(&bind_hash_table, key, ht_parms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) memcpy(rs->rs_bound_key, key, sizeof(rs->rs_bound_key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) rs->rs_bound_addr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) net_get_random_once(&rs->rs_hash_initval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) sizeof(rs->rs_hash_initval));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) rs->rs_bound_port = cpu_to_be16(rover);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) rs->rs_bound_node.next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) rds_sock_addref(rs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (!rhashtable_insert_fast(&bind_hash_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) &rs->rs_bound_node, ht_parms)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *port = rs->rs_bound_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) rs->rs_bound_scope_id = scope_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) rdsdebug("rs %p binding to %pI6c:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) rs, addr, (int)ntohs(*port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) rs->rs_bound_addr = in6addr_any;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) rds_sock_put(rs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) } while (rover++ != last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) void rds_remove_bound(struct rds_sock *rs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (ipv6_addr_any(&rs->rs_bound_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) rdsdebug("rs %p unbinding from %pI6c:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rs, &rs->rs_bound_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ntohs(rs->rs_bound_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) rhashtable_remove_fast(&bind_hash_table, &rs->rs_bound_node, ht_parms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) rds_sock_put(rs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) rs->rs_bound_addr = in6addr_any;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct rds_sock *rs = rds_sk_to_rs(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct in6_addr v6addr, *binding_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct rds_transport *trans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) __u32 scope_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) __be16 port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* We allow an RDS socket to be bound to either IPv4 or IPv6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (addr_len < offsetofend(struct sockaddr, sa_family))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (uaddr->sa_family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (addr_len < sizeof(struct sockaddr_in) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) sin->sin_addr.s_addr == htonl(INADDR_ANY) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) sin->sin_addr.s_addr == htonl(INADDR_BROADCAST) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ipv4_is_multicast(sin->sin_addr.s_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &v6addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) binding_addr = &v6addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) port = sin->sin_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } else if (uaddr->sa_family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int addr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (addr_len < sizeof(struct sockaddr_in6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) addr_type = ipv6_addr_type(&sin6->sin6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (!(addr_type & IPV6_ADDR_UNICAST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) __be32 addr4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!(addr_type & IPV6_ADDR_MAPPED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* It is a mapped address. Need to do some sanity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * checks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) addr4 = sin6->sin6_addr.s6_addr32[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (addr4 == htonl(INADDR_ANY) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) addr4 == htonl(INADDR_BROADCAST) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ipv4_is_multicast(addr4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* The scope ID must be specified for link local address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (addr_type & IPV6_ADDR_LINKLOCAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (sin6->sin6_scope_id == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) scope_id = sin6->sin6_scope_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) binding_addr = &sin6->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) port = sin6->sin6_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* RDS socket does not allow re-binding. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!ipv6_addr_any(&rs->rs_bound_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* Socket is connected. The binding address should have the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * scope ID as the connected address, except the case when one is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * non-link local address (scope_id is 0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (!ipv6_addr_any(&rs->rs_conn_addr) && scope_id &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) rs->rs_bound_scope_id &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) scope_id != rs->rs_bound_scope_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* The transport can be set using SO_RDS_TRANSPORT option before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * socket is bound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (rs->rs_transport) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) trans = rs->rs_transport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!trans->laddr_check ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) trans->laddr_check(sock_net(sock->sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) binding_addr, scope_id) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ret = -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) trans = rds_trans_get_preferred(sock_net(sock->sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) binding_addr, scope_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (!trans) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ret = -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) pr_info_ratelimited("RDS: %s could not find a transport for %pI6c, load rds_tcp or rds_rdma?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) __func__, binding_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) rs->rs_transport = trans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) sock_set_flag(sk, SOCK_RCU_FREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ret = rds_add_bound(rs, binding_addr, &port, scope_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) rs->rs_transport = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) void rds_bind_lock_destroy(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) rhashtable_destroy(&bind_hash_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int rds_bind_lock_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return rhashtable_init(&bind_hash_table, &ht_parms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }