Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <sys/select.h>
- #include <netinet/ip.h>
- #include <arpa/inet.h>
- int get_policy_data(const char *, void **);
- void generate_error(int, const char *, const char *);
- void process_reload_signal(int);
- int create_socket(unsigned short);
- void parse_requests(int, void *, int, const char *, const char *);
- int create_fdset(fd_set *, int *, unsigned, int);
- int * array_add(int *, unsigned, int);
- int * array_remove(int *, unsigned, int);
- void send_policy_info(int, void *, unsigned);
- volatile sig_atomic_t reload_next;
- int main (int argc, char ** argv) {
- if (argc != 2) generate_error(1, *argv, argv[1]);
- void * policydata;
- int policylength = get_policy_data(argv[1], &policydata);
- if (policylength < 0) generate_error(-policylength, *argv, argv[1]);
- reload_next = 0;
- int socketnumber = create_socket(843);
- if (socketnumber < 0) generate_error(2, *argv, argv[1]);
- if (signal(SIGHUP, &process_reload_signal) == SIG_ERR)
- fprintf(stderr, "%s: could not install SIGHUP handler\n", *argv);
- parse_requests(socketnumber, policydata, policylength, *argv, argv[1]);
- close(socketnumber);
- return 0;
- }
- int get_policy_data (const char * filename, void ** data) {
- int fd = open(filename, 0);
- if (fd < 0)
- switch (errno) {
- case EACCES: return -3;
- case ENOENT: case ENOTDIR: return -4;
- default: return -5;
- }
- struct stat statdata;
- if(fstat(fd, &statdata)) {
- close(fd);
- return -5;
- }
- int remainder = statdata.st_size;
- int size = remainder;
- *data = malloc(size + 1);
- char * readp = *data;
- int readsize;
- while (remainder > 0) {
- readsize = read(fd, readp, remainder);
- if (readsize > 0) {
- remainder -= readsize;
- readp += readsize;
- continue;
- }
- if (!readsize) {
- size = readp - ((char *) (*data));
- break;
- }
- if ((errno == EINTR) || (errno = EAGAIN)) continue;
- close(fd);
- if (errno == EISDIR) return -6;
- return -5;
- }
- close(fd);
- ((char *) (*data))[size] = 0;
- return size + 1;
- }
- void generate_error (int error, const char * programname, const char * filename) {
- switch (error) {
- case 1:
- fprintf(stderr, "usage: %s policyfile\n", programname);
- break;
- case 2:
- fprintf(stderr, "%s: could not create listening socket on port 843\n", programname);
- break;
- case 3:
- fprintf(stderr, "%s: permission denied when accessing policy file %s\n", programname, filename);
- break;
- case 4:
- fprintf(stderr, "%s: policy file %s does not exist\n", programname, filename);
- break;
- case 5:
- fprintf(stderr, "%s: unknown error accessing policy file %s\n", programname, filename);
- break;
- case 6:
- fprintf(stderr, "%s: policy file %s is actually a directory\n", programname, filename);
- break;
- }
- exit(error);
- }
- void process_reload_signal (int signalnumber) {
- reload_next = 1;
- }
- int create_socket (unsigned short port) {
- int number = socket(AF_INET, SOCK_STREAM || SOCK_NONBLOCK, 0);
- if (number < 0) return -1;
- struct sockaddr_in sa;
- sa.sin_family = AF_INET;
- sa.sin_port = htons(port);
- sa.sin_addr.s_addr = INADDR_ANY;
- if (bind(number, (struct sockaddr *) &sa, sizeof sa)) {
- close(number);
- return -1;
- }
- if (listen(number, 128)) {
- close(number);
- return -1;
- }
- return number;
- }
- void parse_requests (int socketnumber, void * policydata, int policylength, const char * programname, const char * filename) {
- struct timeval tv = {.tv_sec = 5, .tv_usec = 0};
- struct timeval tvs;
- int cont = 1;
- int result;
- fd_set fdset;
- int * clients = NULL;
- unsigned clientcount = 0;
- int * copy;
- unsigned current, limit;
- while (cont) {
- result = create_fdset(&fdset, clients, clientcount, socketnumber);
- tvs = tv;
- result = select(result, &fdset, NULL, NULL, &tvs);
- if (reload_next) {
- void * newdata;
- int status = get_policy_data(filename, &newdata);
- if (status < 0)
- fprintf(stderr, "%s: could not reload policy data from %s\n", programname, filename);
- else {
- free(policydata);
- policydata = newdata;
- policylength = status;
- }
- reload_next = 0;
- }
- if (result <= 0) continue;
- copy = malloc(clientcount * sizeof(int));
- memcpy(copy, clients, clientcount * sizeof(int));
- limit = clientcount;
- if (FD_ISSET(socketnumber, &fdset)) {
- int newsocket = accept(socketnumber, NULL, NULL);
- if (newsocket > 0) clients = array_add(clients, clientcount ++, newsocket);
- }
- for (current = 0; current < limit; current ++)
- if (FD_ISSET(copy[current], &fdset)) {
- char buffer[1024];
- int reception = recv(copy[current], buffer, 1024, MSG_DONTWAIT);
- if (!reception) {
- close(copy[current]);
- clients = array_remove(clients, clientcount --, copy[current]);
- }
- if (reception <= 0) continue;
- unsigned short pos;
- for (pos = 0; pos < reception; pos ++)
- if (!buffer[pos])
- send_policy_info(copy[current], policydata, policylength);
- }
- free(copy);
- }
- }
- int create_fdset (fd_set * fdset, int * fds, unsigned count, int listener) {
- int * max = fds + count;
- int * current;
- int maxfd = listener + 1;
- FD_ZERO(fdset);
- FD_SET(listener, fdset);
- for (current = fds; current < max; current ++) {
- if (*current >= maxfd) maxfd = *current + 1;
- FD_SET(*current, fdset);
- }
- return maxfd;
- }
- int * array_add (int * array, unsigned length, int new) {
- array = realloc(array, sizeof(int) * (length + 1));
- array[length] = new;
- return array;
- }
- int * array_remove (int * array, unsigned length, int item) {
- if (!length) {
- free(array);
- return NULL;
- }
- unsigned position;
- for (position = 0; position < length; position ++)
- if (array[position] == item) break;
- if (position >= length) return array;
- array[position] = array[-- length];
- return realloc(array, sizeof(int) * length);
- }
- void send_policy_info (int destsocket, void * data, unsigned length) {
- char * pending = data;
- unsigned size = length;
- int status, retries = 0;
- while (size) {
- status = send(destsocket, pending, size, MSG_NOSIGNAL);
- if (status >= 0) {
- retries = 0;
- size -= status;
- pending += status;
- continue;
- }
- if (errno == EPIPE) return;
- retries ++;
- if (retries >= 3) return;
- }
- }
Advertisement
RAW Paste Data
Copied
Advertisement