int main(int argc, char *argv[]) { /* a request */ request_t request = {{0}}; /* resolving hints */ struct addrinfo hints = {0}; /* the address of a client */ struct sockaddr client_address = {0}; /* the daemon data */ daemon_t daemon_data = {{{0}}}; /* the request size */ ssize_t size = 0; /* the client address size */ socklen_t address_size = 0; /* the exit code */ int exit_code = EXIT_FAILURE; /* a received signal */ int received_signal = 0; /* child process ID */ pid_t pid = 0; /* the local address */ struct addrinfo *address = NULL; /* the file path */ const char *path = NULL; /* the transfer mode */ const char *mode = NULL; /* make sure the number of command-line arguments is valid */ if (1 != argc) { PRINT(USAGE); goto end; } /* resolve the local address */ hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_V4MAPPED; if (0 != getaddrinfo(NULL, LISTENING_PORT, &hints, &address)) { goto end; } /* create a socket */ daemon_data.fd = socket(address->ai_family, address->ai_socktype, address->ai_protocol); if (-1 == daemon_data.fd) { goto free_address; } /* set the socket timeout */ if (false == _set_timeout(daemon_data.fd)) { goto end; } /* bind the socket */ if (-1 == bind(daemon_data.fd, address->ai_addr, address->ai_addrlen)) { goto close_socket; } /* open the system log*/ openlog("tftpd", LOG_NDELAY, LOG_DAEMON); /* initialize the daemon */ if (false == daemon_init(&daemon_data, SERVER_ROOT, DAEMON_USER)) { goto close_log; } do { /* wait for a request */ if (false == daemon_wait(&daemon_data, &received_signal)) { break; } /* if the received signal is a termination one, report success */ if (SIGTERM == received_signal) { break; } /* receive the request */ address_size = sizeof(client_address); size = recvfrom(daemon_data.fd, (void *) request.data, sizeof(request.data), 0, &client_address, &address_size); switch (size) { case 0: /* if it was nothing but a scan, ignore it */ continue; case (-1): goto close_log; } /* make sure the request isn't too small */ if (MIN_REQUEST_SIZE > size) { continue; } /* make sure the request is valid */ request.header.opcode = ntohs(request.header.opcode); switch (request.header.opcode) { case PACKET_TYPE_RRQ: case PACKET_TYPE_WRQ: break; default: continue; } /* locate the path */ path = (const char *) &request.data[sizeof(uint16_t)]; /* make sure the path is null-terminated */ mode = memchr((const void *) path, '\0', 1 + NAME_MAX); if (NULL == mode) { continue; } /* skip the null byte */ ++mode; /* spawn a child process */ pid = fork(); switch (pid) { case (-1): goto close_log; case 0: /* handle the request */ if (false == _handle_request(path, mode, request.header.opcode, address, &client_address, address_size)) { goto close_log; } goto success; } } while (1); success: /* report success */ exit_code = EXIT_SUCCESS; close_log: /* close the system log */ closelog(); close_socket: /* close the socket */ (void) close(daemon_data.fd); free_address: /* free the local address */ freeaddrinfo(address); end: return exit_code; }
static void * _handle_accept(void *arg) { /*struct request_params *param = (struct request_params *)arg;*/ int fd = ((struct request_params *)arg)->fd; slurmd_job_t *job = ((struct request_params *)arg)->job; int req; int len; Buf buffer; void *auth_cred; int rc; uid_t uid; gid_t gid; debug3("Entering _handle_accept (new thread)"); xfree(arg); safe_read(fd, &req, sizeof(int)); if (req != REQUEST_CONNECT) { error("First message must be REQUEST_CONNECT"); goto fail; } safe_read(fd, &len, sizeof(int)); buffer = init_buf(len); safe_read(fd, get_buf_data(buffer), len); /* Unpack and verify the auth credential */ auth_cred = g_slurm_auth_unpack(buffer); if (auth_cred == NULL) { error("Unpacking authentication credential: %s", g_slurm_auth_errstr(g_slurm_auth_errno(NULL))); free_buf(buffer); goto fail; } rc = g_slurm_auth_verify(auth_cred, NULL, 2, NULL); if (rc != SLURM_SUCCESS) { error("Verifying authentication credential: %s", g_slurm_auth_errstr(g_slurm_auth_errno(auth_cred))); (void) g_slurm_auth_destroy(auth_cred); free_buf(buffer); goto fail; } /* Get the uid & gid from the credential, then destroy it. */ uid = g_slurm_auth_get_uid(auth_cred, NULL); gid = g_slurm_auth_get_gid(auth_cred, NULL); debug3(" Identity: uid=%d, gid=%d", uid, gid); g_slurm_auth_destroy(auth_cred); free_buf(buffer); rc = SLURM_SUCCESS; safe_write(fd, &rc, sizeof(int)); while (1) { rc = _handle_request(fd, job, uid, gid); if (rc != SLURM_SUCCESS) break; } if (close(fd) == -1) error("Closing accepted fd: %m"); pthread_mutex_lock(&message_lock); message_connections--; pthread_cond_signal(&message_cond); pthread_mutex_unlock(&message_lock); debug3("Leaving _handle_accept"); return NULL; fail: rc = SLURM_FAILURE; safe_write(fd, &rc, sizeof(int)); rwfail: if (close(fd) == -1) error("Closing accepted fd after error: %m"); debug("Leaving _handle_accept on an error"); return NULL; }