int udp_create_socket(uint16_t port, char *local_address) { int s; int value = 1; struct sockaddr_in sox; //__android_log_print(ANDROID_LOG_VERBOSE, "NDKOUT", "error %d: %s)\n",port, local_address); s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if(s < 0){ nbdie("udp: couldn't create socket"); } if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, (void*)&value, sizeof(int)) < 0){ nbdie("udp: couldn't set socket to SO_BROADCAST"); } sox.sin_addr.s_addr = inet_addr(local_address); sox.sin_family = AF_INET; sox.sin_port = htons(port); if(sox.sin_addr.s_addr == INADDR_NONE){ nbdie("udp: couldn't parse local address"); } if(bind(s, (struct sockaddr *)&sox, sizeof(struct sockaddr_in)) < 0){ nbdie("udp: couldn't bind to port (are you running as root?)"); } return s; }
int tcp_listen(char *address, uint16_t port) { int s; struct sockaddr_in serv_addr; /* Get the server address */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(address); serv_addr.sin_port = htons(port); if(serv_addr.sin_addr.s_addr == INADDR_NONE) nbdie("tcp: couldn't parse local address"); /* Create a socket */ s = socket(AF_INET, SOCK_STREAM, 0); if(s < 0) { nbdie("tcp: couldn't create socket"); } else { /* Bind the socket */ if (bind(s, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) nbdie("tcp: couldn't bind to socket"); /* Switch the socket to listen mode. TODO: why 20? */ if(listen(s, 20) < 0) nbdie("tcp: couldn't listen on socket"); } return s; }
void udp_send(int sock, char *address, uint16_t port, void *data, size_t length) { int result; struct sockaddr_in serv_addr; struct hostent *server; /* Look up the host */ server = gethostbyname(address); if(!server) { fprintf(stderr, "Couldn't find host %s\n", address); } else { /* Set up the server address */ memset(&serv_addr, '\0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); memcpy(&serv_addr.sin_addr, server->h_addr_list[0], server->h_length); result = sendto(sock, data, length, 0, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in)); if( result < 0 ) nbdie("udp: couldn't send data"); } }
void sessions_enable_logging(sessions_t *sessions, char *filename) { sessions->log_filename = filename; #ifdef WIN32 fopen_s(&sessions->log, filename, "a"); #else sessions->log = fopen(filename, "a"); #endif if(!sessions->log) nbdie("Failed to open logfile"); fprintf(stderr, "Opened logfile: %s\n", sessions->log_filename); }
size_t udp_read(int s, void *buffer, size_t buffer_length, struct sockaddr_in *from) { size_t received; socklen_t fromlen = sizeof(struct sockaddr_in); memset(from, 0, sizeof(struct sockaddr)); received = recvfrom(s, buffer, buffer_length, 0, (struct sockaddr *)from, &fromlen); if( received < 0 ) nbdie("udp: couldn't receive data"); return received; }
int tcp_accept(int listen, char **address, uint16_t *port) { struct sockaddr_in addr; socklen_t sockaddr_len = sizeof(struct sockaddr_in); int s; s = accept(listen, (struct sockaddr *) &addr, &sockaddr_len); if(s < 0) nbdie("tcp: couldn't accept connection"); *address = inet_ntoa(addr.sin_addr); *port = ntohs(addr.sin_port); return s; }
int tcp_connect(char *host, uint16_t port) { struct sockaddr_in serv_addr; struct hostent *server; /* Create the socket */ int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == -1) { nbdie("tcp: couldn't create socket"); } else { /* Look up the host */ server = gethostbyname(host); if(!server) { s = -1; fprintf(stderr, "Couldn't find host %s\n", host); } else { /* Set up the server address */ memset(&serv_addr, '\0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); memcpy(&serv_addr.sin_addr, server->h_addr_list[0], server->h_length); /* Connect */ if (connect(s, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { s = -1; nberror("tcp: couldn't connect to host"); } } } return s; }
driver_exec_t *driver_exec_create(select_group_t *group, char *process, char *name) { driver_exec_t *driver_exec = (driver_exec_t*) safe_malloc(sizeof(driver_exec_t)); message_options_t options[2]; /* Declare some WIN32 variables needed for starting the sub-process. */ #ifdef WIN32 STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation; SECURITY_ATTRIBUTES sa; #endif driver_exec->process = process; driver_exec->group = group; driver_exec->name = name ? name : process; /* Subscribe to the messages we care about. */ message_subscribe(MESSAGE_DATA_IN, handle_message, driver_exec); /* Set up the session options and create the session. */ options[0].name = "name"; options[0].value.s = driver_exec->name; options[1].name = NULL; driver_exec->session_id = message_post_create_session(options); #ifdef WIN32 /* Create a security attributes structure. This is required to inherit handles. */ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Create the anonymous pipes. */ if(!CreatePipe(&driver_exec->exec_stdin[PIPE_READ], &driver_exec->exec_stdin[PIPE_WRITE], &sa, 0)) DIE("exec: Couldn't create pipe for stdin"); if(!CreatePipe(&driver_exec->exec_stdout[PIPE_READ], &driver_exec->exec_stdout[PIPE_WRITE], &sa, 0)) DIE("exec: Couldn't create pipe for stdout"); fprintf(stderr, "Attempting to load the program: %s\n", driver_exec->process); /* Initialize the STARTUPINFO structure. */ ZeroMemory(&startupInfo, sizeof(STARTUPINFO)); startupInfo.cb = sizeof(STARTUPINFO); startupInfo.dwFlags = STARTF_USESTDHANDLES; startupInfo.hStdInput = driver_exec->exec_stdin[PIPE_READ]; startupInfo.hStdOutput = driver_exec->exec_stdout[PIPE_WRITE]; startupInfo.hStdError = driver_exec->exec_stdout[PIPE_WRITE]; /* Initialize the PROCESS_INFORMATION structure. */ ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION)); /* Create the actual process with an overly-complicated CreateProcess function. */ if(!CreateProcessA(NULL, driver_exec->process, 0, &sa, TRUE, CREATE_NO_WINDOW, 0, NULL, &startupInfo, &processInformation)) { fprintf(stderr, "Failed to create the process"); exit(1); } /* Save the process id and the handle. */ driver_exec->pid = processInformation.dwProcessId; driver_exec->exec_handle = processInformation.hProcess; /* Close the duplicate pipes we created -- this lets us detect the proicess termination. */ CloseHandle(driver_exec->exec_stdin[PIPE_READ]); CloseHandle(driver_exec->exec_stdout[PIPE_WRITE]); CloseHandle(driver_exec->exec_stdout[PIPE_WRITE]); fprintf(stderr, "Successfully created the process!\n\n"); /* Create a socket_id value - this is a totally arbitrary value that's only used so we can find this entry later. */ driver_exec->socket_id = --driver_exec->socket_id; /* On Windows, add the sub-process's stdout as a pipe. */ select_group_add_pipe(driver_exec->group, driver_exec->socket_id, driver_exec->exec_stdout[PIPE_READ], driver_exec); select_set_recv(driver_exec->group, driver_exec->socket_id, exec_callback); select_set_closed(driver_exec->group, driver_exec->socket_id, exec_closed_callback); #else LOG_INFO("Attempting to start process '%s'...", driver_exec->process); /* Create communication channels. */ if(pipe(driver_exec->pipe_stdin) == -1) { LOG_FATAL("exec: couldn't create pipe (%d)", errno); exit(1); } if(pipe(driver_exec->pipe_stdout) == -1) { LOG_FATAL("exec: couldn't create pipe (%d)", errno); exit(1); } driver_exec->pid = fork(); if(driver_exec->pid == -1) { LOG_FATAL("exec: couldn't create process (%d)", errno); exit(1); } /* If we're in the child process... */ if(driver_exec->pid == 0) { /* Copy the pipes. */ if(dup2(driver_exec->pipe_stdin[PIPE_READ], STDIN_FILENO) == -1) nbdie("exec: couldn't duplicate STDIN handle"); if(dup2(driver_exec->pipe_stdout[PIPE_WRITE], STDOUT_FILENO) == -1) nbdie("exec: couldn't duplicate STDOUT handle"); if(dup2(driver_exec->pipe_stdout[PIPE_WRITE], STDERR_FILENO) == -1) nbdie("exec: couldn't duplicate STDERR handle"); /* Execute the new process. */ execlp("/bin/sh", "sh", "-c", driver_exec->process, (char*) NULL); /* If execlp returns, bad stuff happened. */ LOG_FATAL("exec: execlp failed (%d)", errno); exit(1); } LOG_WARNING("Started: %s (pid: %d)", driver_exec->process, driver_exec->pid); close(driver_exec->pipe_stdin[PIPE_READ]); close(driver_exec->pipe_stdout[PIPE_WRITE]); /* Add the sub-process's stdout as a socket. */ select_group_add_socket(driver_exec->group, driver_exec->pipe_stdout[PIPE_READ], SOCKET_TYPE_STREAM, driver_exec); select_set_recv(driver_exec->group, driver_exec->pipe_stdout[PIPE_READ], exec_callback); select_set_closed(driver_exec->group, driver_exec->pipe_stdout[PIPE_READ], exec_closed_callback); #endif return driver_exec; }
/* This is called after the drivers are created, to kick things off. */ static void handle_start(driver_exec_t *driver) { message_post_create_session(); /* Create the exec socket */ #ifdef WIN32 /* TODO */ #else LOG_INFO("Attempting to start process '%s'...", driver->process); /* Create communication channels. */ if(pipe(driver->pipe_stdin) == -1) { LOG_FATAL("exec: couldn't create pipe (%d)", errno); exit(1); } if(pipe(driver->pipe_stdout) == -1) { LOG_FATAL("exec: couldn't create pipe (%d)", errno); exit(1); } driver->pid = fork(); if(driver->pid == -1) { LOG_FATAL("exec: couldn't create process (%d)", errno); exit(1); } /* If we're in the child process... */ if(driver->pid == 0) { /* Copy the pipes. */ if(dup2(driver->pipe_stdin[PIPE_READ], STDIN_FILENO) == -1) nbdie("exec: couldn't duplicate STDIN handle"); if(dup2(driver->pipe_stdout[PIPE_WRITE], STDOUT_FILENO) == -1) nbdie("exec: couldn't duplicate STDOUT handle"); if(dup2(driver->pipe_stdout[PIPE_WRITE], STDERR_FILENO) == -1) nbdie("exec: couldn't duplicate STDERR handle"); /* Execute the new process. */ execlp("/bin/sh", "sh", "-c", driver->process, (char*) NULL); /* If execlp returns, bad stuff happened. */ LOG_FATAL("exec: execlp failed (%d)", errno); exit(1); } LOG_WARNING("Started: %s (pid: %d)", driver->process, driver->pid); close(driver->pipe_stdin[PIPE_READ]); close(driver->pipe_stdout[PIPE_WRITE]); /* Add the sub-process's stdout as a socket. */ select_group_add_socket(driver->group, driver->pipe_stdout[PIPE_READ], SOCKET_TYPE_STREAM, driver); select_set_recv(driver->group, driver->pipe_stdout[PIPE_READ], exec_callback); select_set_closed(driver->group, driver->pipe_stdout[PIPE_READ], exec_closed_callback); #endif }
static NBBOOL session_attach_process(sessions_t *sessions, session_t *session, char *process) { #ifdef WIN32 STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation; SECURITY_ATTRIBUTES sa; session_group_t *session_group = (session_group_t*) safe_malloc(sizeof(session_group_t)); session_group->session = session; session_group->sessions = sessions; /* Create a security attributes structure. This is required to inherit handles. */ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Create the anonymous pipes. */ if(!CreatePipe(&session->exec_stdin[PIPE_READ], &session->exec_stdin[PIPE_WRITE], &sa, 0)) nbdie("exec: Couldn't create pipe for stdin"); if(!CreatePipe(&session->exec_stdout[PIPE_READ], &session->exec_stdout[PIPE_WRITE], &sa, 0)) nbdie("exec: Couldn't create pipe for stdout"); fprintf(stderr, "Attempting to load the program: %s\n", process); /* Initialize the STARTUPINFO structure. */ ZeroMemory(&startupInfo, sizeof(STARTUPINFO)); startupInfo.cb = sizeof(STARTUPINFO); startupInfo.dwFlags = STARTF_USESTDHANDLES; startupInfo.hStdInput = session->exec_stdin[PIPE_READ]; startupInfo.hStdOutput = session->exec_stdout[PIPE_WRITE]; if(!sessions->exec_no_stderr) startupInfo.hStdError = session->exec_stdout[PIPE_WRITE]; /* Initialize the PROCESS_INFORMATION structure. */ ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION)); /* Create the actual process with an overly-complicated CreateProcess function. */ if(!CreateProcessA(NULL, process, 0, &sa, TRUE, CREATE_NO_WINDOW, 0, NULL, &startupInfo, &processInformation)) { fprintf(stderr, "Failed to create the process"); exit(1); } /* Save the process id and the handle. */ session->pid = processInformation.dwProcessId; session->exec_handle = processInformation.hProcess; session->socket_id = --sessions->current_socket_id; /* Close the duplicate pipes we created -- this lets us detect the proicess termination. */ CloseHandle(session->exec_stdin[PIPE_READ]); CloseHandle(session->exec_stdout[PIPE_WRITE]); if(!sessions->exec_no_stderr) CloseHandle(session->exec_stdout[PIPE_WRITE]); fprintf(stderr, "Successfully created the process!\n\n"); /* On Windows, add the sub-process's stdout as a pipe. */ select_group_add_pipe(sessions->select_group, session->socket_id, session->exec_stdout[PIPE_READ], session_group); select_set_recv(sessions->select_group, session->socket_id, exec_callback); select_set_closed(sessions->select_group, session->socket_id, exec_closed_callback); #else session_group_t *session_group = (session_group_t*) safe_malloc(sizeof(session_group_t)); session_group->session = session; session_group->sessions = sessions; fprintf(stderr, "Attempting to start process '%s' for session %s\n", process, session->name); /* Create communication channels. */ if(pipe(session->exec_stdin) == -1) nbdie("exec: couldn't create pipe for STDIN"); if(pipe(session->exec_stdout) == -1) nbdie("exec: couldn't create pipe for STDOUT"); session->pid = fork(); if(session->pid == -1) nbdie("exec: couldn't create process"); if(session->pid == 0) { /* Copy the pipes. */ if(dup2(session->exec_stdin[PIPE_READ], STDIN_FILENO) == -1) nbdie("exec: couldn't duplicate STDIN handle"); if(dup2(session->exec_stdout[PIPE_WRITE], STDOUT_FILENO) == -1) nbdie("exec: couldn't duplicate STDOUT handle"); if(sessions->exec_no_stderr) { session->exec_stdout[PIPE_WRITE] = 0; } else { if(dup2(session->exec_stdout[PIPE_WRITE], STDERR_FILENO) == -1) nbdie("exec: couldn't duplicate STDERR handle"); } /* Execute the new process. */ execlp("/bin/sh", "sh", "-c", process, (char*) NULL); /* If execlp returns, bad stuff happened. */ fprintf(stderr, "exec: execlp failed"); return FALSE; } fprintf(stderr, "Started: %s (pid: %d)\n", process, session->pid); close(session->exec_stdin[PIPE_READ]); close(session->exec_stdout[PIPE_WRITE]); /* On Linux, add the sub-process's stdout as a socket. */ select_group_add_socket(sessions->select_group, session->exec_stdout[PIPE_READ], SOCKET_TYPE_STREAM, session_group); select_set_recv(sessions->select_group, session->exec_stdout[PIPE_READ], exec_callback); select_set_closed(sessions->select_group, session->exec_stdout[PIPE_READ], exec_closed_callback); #endif return TRUE; }