- CDEBUG(D_NET, "Accept %s from %u.%u.%u.%u%s\n",
- libcfs_nid2str(cr.acr_nid), HIPQUAD(peer_ip),
- blind_ni == NULL ? "" : " (blind)");
-
- if (blind_ni == NULL) {
- /* called by the acceptor: call into the requested NI... */
- rc = ni->ni_lnd->lnd_accept(ni, sock);
- } else {
- /* portals_compatible set and the (only) NI called me to verify
- * and skip the connection request... */
- LASSERT (the_lnet.ln_ptlcompat != 0);
- LASSERT (ni == blind_ni);
- rc = 0;
- }
-
- lnet_ni_decref(ni);
- return rc;
-}
-EXPORT_SYMBOL(lnet_accept);
-
-int
-lnet_acceptor(void *arg)
-{
- char name[16];
- cfs_socket_t *newsock;
- int rc;
- int n_acceptor_nis;
- __u32 magic;
- __u32 peer_ip;
- int peer_port;
- lnet_ni_t *blind_ni = NULL;
- int secure = (int)((unsigned long)arg);
-
- LASSERT (lnet_acceptor_state.pta_sock == NULL);
-
- if (the_lnet.ln_ptlcompat != 0) {
- /* When portals_compatibility is enabled, peers may connect
- * without sending an acceptor connection request. There is no
- * ambiguity about which network the peer wants to connect to
- * since there can only be 1 network, so I pass connections
- * "blindly" to it. */
- n_acceptor_nis = lnet_count_acceptor_nis(&blind_ni);
- LASSERT (n_acceptor_nis == 1);
- LASSERT (blind_ni != NULL);
- }
-
- snprintf(name, sizeof(name), "acceptor_%03d", accept_port);
- cfs_daemonize(name);
- cfs_block_allsigs();
-
- rc = libcfs_sock_listen(&lnet_acceptor_state.pta_sock,
- 0, accept_port, accept_backlog);
- if (rc != 0) {
- if (rc == -EADDRINUSE)
- LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port"
- " %d: port already in use\n",
- accept_port);
- else
- LCONSOLE_ERROR_MSG(0x123, "Can't start acceptor on port "
- "%d: unexpected error %d\n",
- accept_port, rc);
-
- lnet_acceptor_state.pta_sock = NULL;
- } else {
- LCONSOLE(0, "Accept %s, port %d%s\n",
- accept, accept_port,
- blind_ni == NULL ? "" : " (proto compatible)");
- }
-
- /* set init status and unblock parent */
- lnet_acceptor_state.pta_shutdown = rc;
- mutex_up(&lnet_acceptor_state.pta_signal);
-
- if (rc != 0)
- return rc;
-
- while (!lnet_acceptor_state.pta_shutdown) {
-
- rc = libcfs_sock_accept(&newsock, lnet_acceptor_state.pta_sock);
- if (rc != 0) {
- if (rc != -EAGAIN) {
- CWARN("Accept error %d: pausing...\n", rc);
- cfs_pause(cfs_time_seconds(1));
- }
- continue;
- }
-
- rc = libcfs_sock_getaddr(newsock, 1, &peer_ip, &peer_port);
- if (rc != 0) {
- CERROR("Can't determine new connection's address\n");
- goto failed;
- }
-
- if (secure && peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) {
- CERROR("Refusing connection from %u.%u.%u.%u: "
- "insecure port %d\n",
- HIPQUAD(peer_ip), peer_port);
- goto failed;
- }
-
- if (blind_ni != NULL) {
- rc = blind_ni->ni_lnd->lnd_accept(blind_ni, newsock);
- if (rc != 0) {
- CERROR("NI %s refused 'blind' connection from "
- "%u.%u.%u.%u\n",
- libcfs_nid2str(blind_ni->ni_nid),
- HIPQUAD(peer_ip));
- goto failed;
- }
- continue;
- }
-
- rc = libcfs_sock_read(newsock, &magic, sizeof(magic),
- accept_timeout);
- if (rc != 0) {
- CERROR("Error %d reading connection request from "
- "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
- goto failed;
- }
-
- rc = lnet_accept(NULL, newsock, magic);
- if (rc != 0)
- goto failed;
-
- continue;
-
- failed:
- libcfs_sock_release(newsock);
- }
-
- libcfs_sock_release(lnet_acceptor_state.pta_sock);
- lnet_acceptor_state.pta_sock = NULL;
-
- if (blind_ni != NULL)
- lnet_ni_decref(blind_ni);
-
- LCONSOLE(0,"Acceptor stopping\n");
-
- /* unblock lnet_acceptor_stop() */
- mutex_up(&lnet_acceptor_state.pta_signal);
- return 0;
-}
-
-int
-lnet_acceptor_start(void)
-{
- long pid;
- long secure;
-
- LASSERT (lnet_acceptor_state.pta_sock == NULL);
- init_mutex_locked(&lnet_acceptor_state.pta_signal);
-
- if (!strcmp(accept, "secure")) {
- secure = 1;
- } else if (!strcmp(accept, "all")) {
- secure = 0;
- } else if (!strcmp(accept, "none")) {
- return 0;
- } else {
- LCONSOLE_ERROR_MSG(0x124, "Can't parse 'accept=\"%s\"'\n",
- accept);
- return -EINVAL;
- }
-
- if (lnet_count_acceptor_nis(NULL) == 0) /* not required */
- return 0;
-
- pid = cfs_kernel_thread(lnet_acceptor, (void *)secure, 0);
- if (pid < 0) {
- CERROR("Can't start acceptor thread: %ld\n", pid);
- return -ESRCH;
- }
-
- mutex_down(&lnet_acceptor_state.pta_signal); /* wait for acceptor to startup */
-
- if (!lnet_acceptor_state.pta_shutdown) {
- /* started OK */
- LASSERT (lnet_acceptor_state.pta_sock != NULL);
- return 0;
- }
-
- LASSERT (lnet_acceptor_state.pta_sock == NULL);
- return -ENETDOWN;
-}
-
-void
-lnet_acceptor_stop(void)
-{
- if (lnet_acceptor_state.pta_sock == NULL) /* not running */
- return;
-
- lnet_acceptor_state.pta_shutdown = 1;
- libcfs_sock_abort_accept(lnet_acceptor_state.pta_sock);
-
- /* block until acceptor signals exit */
- mutex_down(&lnet_acceptor_state.pta_signal);
-}
-
-#else /* __KERNEL__ */
-#ifdef HAVE_LIBPTHREAD
-
-static char *accept_type;
-static int accept_port = 988;
-static int accept_backlog;
-static int accept_timeout;
-
-struct {
- int pta_shutdown;
- int pta_sock;
- struct cfs_completion pta_completion;
-} lnet_acceptor_state;
-
-int
-lnet_acceptor_port(void)
-{
- return accept_port;
-}
-
-int
-lnet_parse_int_tunable(int *value, char *name, int dflt)
-{
- char *env = getenv(name);
- char *end;
-
- if (env == NULL) {
- *value = dflt;
- return 0;
- }
-
- *value = strtoull(env, &end, 0);
- if (*end == 0)
- return 0;
-
- CERROR("Can't parse tunable %s=%s\n", name, env);
- return -EINVAL;
-}
-
-int
-lnet_parse_string_tunable(char **value, char *name, char *dflt)
-{
- char *env = getenv(name);
-
- if (env == NULL)
- *value = dflt;
- else
- *value = env;
-
- return 0;
-}
-
-int
-lnet_acceptor_get_tunables()
-{
- int rc;
- rc = lnet_parse_string_tunable(&accept_type, "LNET_ACCEPT", "secure");
-
- if (rc != 0)
- return rc;
-
- rc = lnet_parse_int_tunable(&accept_port, "LNET_ACCEPT_PORT", 988);
-
- if (rc != 0)
- return rc;
-
- rc = lnet_parse_int_tunable(&accept_backlog, "LNET_ACCEPT_BACKLOG", 127);
-
- if (rc != 0)
- return rc;
-
- rc = lnet_parse_int_tunable(&accept_timeout, "LNET_ACCEPT_TIMEOUT", 5);
-
- if (rc != 0)
- return rc;
-
- CDEBUG(D_NET, "accept_type = %s\n", accept_type);
- CDEBUG(D_NET, "accept_port = %d\n", accept_port);
- CDEBUG(D_NET, "accept_backlog = %d\n", accept_backlog);
- CDEBUG(D_NET, "accept_timeout = %d\n", accept_timeout);
- return 0;
-}
-
-static inline int
-lnet_accept_magic(__u32 magic, __u32 constant)
-{
- return (magic == constant ||
- magic == __swab32(constant));
-}
-
-/* user-land lnet_accept() isn't used by any LND's directly. So, we don't
- * do it visible outside acceptor.c and we can change its prototype
- * freely */
-static int
-lnet_accept(int sock, __u32 magic, __u32 peer_ip, int peer_port)
-{
- int rc, flip;
- lnet_acceptor_connreq_t cr;
- lnet_ni_t *ni;
-
- if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) {
- LCONSOLE_ERROR("Refusing connection from %u.%u.%u.%u magic %08x: "
- "unsupported acceptor protocol\n",
- HIPQUAD(peer_ip), magic);
- return -EPROTO;
- }
-
- flip = (magic != LNET_PROTO_ACCEPTOR_MAGIC);
-
- rc = libcfs_sock_read(sock, &cr.acr_version,
- sizeof(cr.acr_version),
- accept_timeout);
- if (rc != 0) {
- CERROR("Error %d reading connection request version from "
- "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
- return -EIO;
- }
-
- if (flip)
- __swab32s(&cr.acr_version);
-
- if (cr.acr_version != LNET_PROTO_ACCEPTOR_VERSION)
- return -EPROTO;
-
- rc = libcfs_sock_read(sock, &cr.acr_nid,
- sizeof(cr) -
- offsetof(lnet_acceptor_connreq_t, acr_nid),
- accept_timeout);
- if (rc != 0) {
- CERROR("Error %d reading connection request from "
- "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
- return -EIO;
- }
-
- if (flip)
- __swab64s(&cr.acr_nid);
-
- ni = lnet_net2ni(LNET_NIDNET(cr.acr_nid));
-
- if (ni == NULL || /* no matching net */
- ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */
- if (ni != NULL)
- lnet_ni_decref(ni);
- LCONSOLE_ERROR("Refusing connection from %u.%u.%u.%u for %s: "
- " No matching NI\n",
- HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid));
- return -EPERM;
- }
-
- if (ni->ni_lnd->lnd_accept == NULL) {
- lnet_ni_decref(ni);
- LCONSOLE_ERROR("Refusing connection from %u.%u.%u.%u for %s: "
- " NI doesn not accept IP connections\n",
- HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid));
- return -EPERM;
- }
-