int validate_socket( int psock) { int rc = PBSE_NONE; static char id[] = "validate_socket"; char tmp_buf[LOCAL_LOG_BUF]; char write_buf[1024]; char *read_buf = NULL; long long read_buf_len = 0; uid_t myrealuid; int local_socket = 0; int parent_client_socket = 0; struct passwd *pwent; char *err_msg = NULL; char *l_server = NULL; int l_server_len = 0; unsigned short af_family; long long code = -1; int write_buf_len = 0; int local_errno; myrealuid = getuid(); if ((pwent = getpwuid(myrealuid)) == NULL) { snprintf(tmp_buf, LOCAL_LOG_BUF, "cannot get account info: uid %d, errno %d (%s)\n", (int)myrealuid, errno, strerror(errno)); log_event(PBSEVENT_ADMIN,PBS_EVENTCLASS_SERVER,id,tmp_buf); } else if ((rc = get_hostaddr_hostent_af(&local_errno, AUTH_IP, &af_family, &l_server, &l_server_len)) != PBSE_NONE) { } else if ((rc = get_parent_client_socket(psock, &parent_client_socket)) != PBSE_NONE) { } else { /* format is: * trq_system|trq_port|Validation_type|user|psock| */ sprintf(write_buf, "%d|%s|%d|%d|%d|%s|%d|", (int)strlen(server_name), server_name, server_port, AUTH_TYPE_IFF, (int)strlen(pwent->pw_name), pwent->pw_name, parent_client_socket); /* * total_length|val */ write_buf_len = strlen(write_buf); if ((local_socket = socket_get_tcp()) <= 0) { fprintf(stderr, "socket_get_tcp error\n"); rc = PBSE_SOCKET_FAULT; } else if ((rc = socket_connect(&local_socket, l_server, l_server_len, AUTH_PORT, AF_INET, 0, &err_msg)) != PBSE_NONE) { fprintf(stderr, "socket_connect error (VERIFY THAT trqauthd IS RUNNING)\n"); } else if ((rc = socket_write(local_socket, write_buf, write_buf_len)) != write_buf_len) { rc = PBSE_SOCKET_WRITE; fprintf(stderr, "socket_write error\n"); } else if ((rc = socket_read_num(local_socket, &code)) != PBSE_NONE) { fprintf(stderr, "socket_read_num error\n"); } else if ((rc = socket_read_str(local_socket, &read_buf, &read_buf_len)) != PBSE_NONE) { fprintf(stderr, "socket_read_str error\n"); } else if ((rc = parse_daemon_response(code, read_buf_len, read_buf)) != PBSE_NONE) { fprintf(stderr, "parse_daemon_response error\n"); } else { if (getenv("PBSDEBUG")) { fprintf(stderr, "%s : Connection authorized (server socket %d)\n", id, parent_client_socket); } socket_close(local_socket); } } if (rc != PBSE_NONE) { if (err_msg != NULL) { fprintf(stderr, "Error in connection to trqauthd (%d)-[%s]\n", rc, err_msg); } } if (err_msg != NULL) free(err_msg); if (read_buf != NULL) free(read_buf); return rc; }
/* Note, in extremely high load cases, the alloc value in /proc/net/sockstat can exceed the max value. This will substantially slow down throughput and generate connection failures (accept gets a EMFILE error). As the client is designed to run on each submit host, that issue shouldn't occur. The client must be restarted to clear out this issue. */ int start_listener( const char *server_ip, int server_port, void *(*process_meth)(void *)) { struct sockaddr_in adr_svr; struct sockaddr_in adr_client; int rc = PBSE_NONE; int sockoptval = 1; int len_inet = sizeof(struct sockaddr_in); int *new_conn_port = NULL; int listen_socket = 0; int total_cntr = 0; pthread_t tid; pthread_attr_t t_attr; int objclass = 0; char msg_started[1024]; memset(&adr_svr, 0, sizeof(adr_svr)); adr_svr.sin_family = AF_INET; if (!(adr_svr.sin_port = htons(server_port))) { } else if ((adr_svr.sin_addr.s_addr = inet_addr(server_ip)) == INADDR_NONE) { rc = PBSE_SOCKET_FAULT; } else if ((listen_socket = socket_get_tcp()) < 0) { /* Can not get socket for listening */ rc = PBSE_SOCKET_FAULT; } else if (bind(listen_socket, (struct sockaddr *)&adr_svr, sizeof(struct sockaddr_in)) == -1) { /* Can not bind local socket */ rc = PBSE_SOCKET_FAULT; } else if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&sockoptval, sizeof(sockoptval)) == -1) { rc = PBSE_SOCKET_FAULT; } else if (listen(listen_socket, 128) == -1) { /* Can not listener on local socket */ rc = PBSE_SOCKET_LISTEN; } else if ((rc = pthread_attr_init(&t_attr)) != 0) { /* Can not init thread attribute structure */ rc = PBSE_THREADATTR; } else if ((rc = pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED)) != 0) { /* Can not set thread initial state as detached */ pthread_attr_destroy(&t_attr); } else { log_get_set_eventclass(&objclass, GETV); if (objclass == PBS_EVENTCLASS_TRQAUTHD) { snprintf(msg_started, sizeof(msg_started), "TORQUE authd daemon started and listening on IP:port %s:%d", server_ip, server_port); log_event(PBSEVENT_SYSTEM | PBSEVENT_FORCE, PBS_EVENTCLASS_TRQAUTHD, msg_daemonname, msg_started); } while (1) { if ((new_conn_port = (int *)calloc(1, sizeof(int))) == NULL) { printf("Error allocating new connection handle on accept.\n"); break; } if ((*new_conn_port = accept(listen_socket, (struct sockaddr *)&adr_client, (socklen_t *)&len_inet)) == -1) { if (errno == EMFILE) { sleep(1); printf("Temporary pause\n"); } else { printf("error in accept %s\n", strerror(errno)); break; } errno = 0; free(new_conn_port); new_conn_port = NULL; } else { if (debug_mode == TRUE) { process_meth((void *)new_conn_port); } else { pthread_create(&tid, &t_attr, process_meth, (void *)new_conn_port); } } if (debug_mode == TRUE) { if (total_cntr % 1000 == 0) { printf("Total requests: %d\n", total_cntr); } total_cntr++; } } if (new_conn_port != NULL) { free(new_conn_port); } pthread_attr_destroy(&t_attr); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, "net_srvr", "Socket close of network listener requested"); } if (listen_socket != -1) close(listen_socket); return(rc); } /* END start_listener() */
int socket_get_tcp_priv() { int priv_port = 0, local_socket = 0; int cntr = 0; #ifdef HAVE_RRESVPORT int on = 1; struct linger l_delay; #endif int rc = PBSE_NONE; struct sockaddr_in local; int flags; memset(&local, 0, sizeof(struct sockaddr_in)); local.sin_family = AF_INET; /* If any of the following 2 succeed (negative conditions) jump to else below * else run the default */ #ifdef HAVE_RRESVPORT memset(&l_delay, 0, sizeof(struct linger)); l_delay.l_onoff = 0; if ((local_socket = rresvport(&priv_port)) != -1) { if (setsockopt(local_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) == -1) { rc = PBSE_SOCKET_FAULT; } else if (setsockopt(local_socket, SOL_SOCKET, SO_LINGER, &l_delay, sizeof(struct linger)) == -1) { rc = PBSE_SOCKET_FAULT; } } if (rc == PBSE_NONE) { /* Success case */ priv_port = local_socket; } else if ((local_socket = socket_get_tcp()) > 0) #else #ifdef HAVE_BINDRESVPORT if ((local_socket = socket_get_tcp()) > 0) { if ((rc = bindresvport(local_socket, &local)) == 0) { /* Success case */ priv_port = ntohs(local.sin_port); } else { rc = PBSE_SOCKET_FAULT; } } else rc = PBSE_SOCKET_FAULT; if (rc != PBSE_NONE) #else /* Default */ if ((local_socket = socket_get_tcp()) > 0) #endif #endif { /* According to the notes in the previous code: * bindresvport seems to cause connect() failures in some odd corner case * when talking to a local daemon. So we'll only try this once and * fallback to the slow loop around bind() if connect() fails * with EADDRINUSE or EADDRNOTAVAIL. * http://www.supercluster.org/pipermail/torqueusers/2006-June/003740.html */ flags = fcntl(local_socket, F_GETFL); flags |= O_NONBLOCK; fcntl(local_socket, F_SETFL, flags); priv_port = get_random_reserved_port(); while (cntr < RES_PORT_RETRY) { if (++priv_port >= RES_PORT_END) priv_port = RES_PORT_START; local.sin_port = htons(priv_port); if (((rc = bind(local_socket, (struct sockaddr *)&local, sizeof(struct sockaddr))) < 0) && ((rc == EADDRINUSE) || (errno == EADDRNOTAVAIL) || (errno == EINVAL) || (rc == EINPROGRESS))) { cntr++; } else { rc = PBSE_NONE; break; } } if (cntr >= RES_PORT_RETRY) { close(local_socket); rc = PBSE_SOCKET_FAULT; errno = PBSE_SOCKET_FAULT; local_socket = -1; } } else { /* If something worked the first time you end up here */ rc = PBSE_NONE; } if (rc != PBSE_NONE) { local_socket = -1; } return local_socket; } /* END socket_get_tcp_priv() */