int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; struct sockaddr_in *sin = (struct sockaddr_in *)uaddr; struct rds_sock *rs = rds_sk_to_rs(sk); struct rds_transport *trans; int ret = 0; lock_sock(sk); if (addr_len != sizeof(struct sockaddr_in) || sin->sin_family != AF_INET || rs->rs_bound_addr || sin->sin_addr.s_addr == htonl(INADDR_ANY)) { ret = -EINVAL; goto out; } ret = rds_add_bound(rs, sin->sin_addr.s_addr, &sin->sin_port); if (ret) goto out; if (rs->rs_transport) { /* previously bound */ trans = rs->rs_transport; if (trans->laddr_check(sock_net(sock->sk), sin->sin_addr.s_addr) != 0) { ret = -ENOPROTOOPT; rds_remove_bound(rs); } else { ret = 0; } goto out; } trans = rds_trans_get_preferred(sock_net(sock->sk), sin->sin_addr.s_addr); if (!trans) { ret = -EADDRNOTAVAIL; rds_remove_bound(rs); pr_info_ratelimited("RDS: %s could not find a transport for %pI4, load rds_tcp or rds_rdma?\n", __func__, &sin->sin_addr.s_addr); goto out; } rs->rs_transport = trans; ret = 0; out: release_sock(sk); return ret; }
int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; struct sockaddr_in *sin = (struct sockaddr_in *)uaddr; struct rds_sock *rs = rds_sk_to_rs(sk); struct rds_transport *trans; int ret = 0; lock_sock(sk); if (addr_len != sizeof(struct sockaddr_in) || sin->sin_family != AF_INET || rs->rs_bound_addr || sin->sin_addr.s_addr == htonl(INADDR_ANY)) { ret = -EINVAL; goto out; } ret = rds_add_bound(rs, sin->sin_addr.s_addr, &sin->sin_port); if (ret) goto out; trans = rds_trans_get_preferred(sin->sin_addr.s_addr); if (trans == NULL) { ret = -EADDRNOTAVAIL; rds_remove_bound(rs); if (printk_ratelimit()) printk(KERN_INFO "RDS: rds_bind() could not find a transport, " "load rds_tcp or rds_rdma?\n"); goto out; } rs->rs_transport = trans; ret = 0; out: release_sock(sk); return ret; }