Merge pull request #38 from nnnn20430/master - fiche - A pastebin adjusted for gopher use
 (HTM) git clone git://vernunftzentrum.de/fiche.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 44b908ff2b5fb333b5faa42394ec4e9d4694d9da
 (DIR) parent 55ef361999e27438d94f06f933b4221bcafee686
 (HTM) Author: solusipse <solus1ps3@gmail.com>
       Date:   Sat,  9 Jul 2016 17:04:05 +0200
       
       Merge pull request #38 from nnnn20430/master
       
       added IPv6 support #2
       Diffstat:
         README.md                           |      10 +++++++++-
         fiche.c                             |     130 ++++++++++++++++++++++++++++---
         fiche.h                             |      17 +++++++++++++++++
       
       3 files changed, 145 insertions(+), 12 deletions(-)
       ---
 (DIR) diff --git a/README.md b/README.md
       @@ -47,7 +47,7 @@ providing fiche-based service all the time on this address `solusipse.net` and t
        ## Server-side usage ##
        
        ```
       -usage: fiche [-DepbsdolBuw].
       +usage: fiche [-D6epbsdSolBuw].
                     [-d domain] [-p port] [-s slug size]
                     [-o output directory] [-B buffer size] [-u user name]
                     [-l log file] [-b banlist] [-w whitelist]
       @@ -189,6 +189,14 @@ fiche -e
        
        -----------------
        
       +#### Use IPv6 ####
       +
       +this will allow fiche to accept connections from IPv6 clients:
       +
       +fiche -6
       +
       +-----------------
       +
        #### Examples ####
        
        Logging connections with banlist:
 (DIR) diff --git a/fiche.c b/fiche.c
       @@ -59,8 +59,21 @@ int main(int argc, char **argv)
            listen_socket = create_socket();
            setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));
        
       -    server_address = set_address(server_address);
       -    bind_to_port(listen_socket, server_address);
       +#if (HAVE_INET6)
       +    struct sockaddr_in6 server_address6;
       +    if (IPv6)
       +    {
       +        server_address6 = set_address6(server_address6);
       +        bind_to_port6(listen_socket, server_address6);
       +    }
       +    else
       +    {
       +#else
       +    if (1) {
       +#endif
       +        server_address = set_address(server_address);
       +        bind_to_port(listen_socket, server_address);
       +    }
        
            if (DAEMON)
            {
       @@ -81,9 +94,23 @@ int main(int argc, char **argv)
        void *thread_connection(void *args)
        {
            int connection_socket = ((struct thread_arguments *) args ) -> connection_socket;
       -    struct sockaddr_in client_address = ((struct thread_arguments *) args ) -> client_address;
       -
       -    struct client_data data = get_client_address(client_address);
       +    struct sockaddr_in client_address;
       +    struct client_data data;
       +#if (HAVE_INET6)
       +    struct sockaddr_in6 client_address6;
       +    if (IPv6)
       +    {
       +        client_address6 = ((struct thread_arguments *) args ) -> client_address6;
       +        data = get_client_address6(client_address6);
       +    }
       +    else
       +    {
       +#else
       +    if (1) {
       +#endif
       +        client_address = ((struct thread_arguments *) args ) -> client_address;
       +        data = get_client_address(client_address);
       +    }
        
            char buffer[BUFSIZE];
            bzero(buffer, BUFSIZE);
       @@ -139,8 +166,24 @@ void perform_connection(int listen_socket)
            pthread_t thread_id;
            struct sockaddr_in client_address;
        
       -    int address_length = sizeof(client_address);
       -    int connection_socket = accept(listen_socket, (struct sockaddr *) &client_address, (void *) &address_length);
       +    int address_length;
       +    int connection_socket;
       +
       +#if (HAVE_INET6)
       +    struct sockaddr_in6 client_address6;
       +    if (IPv6)
       +    {
       +        address_length = sizeof(client_address6);
       +        connection_socket = accept(listen_socket, (struct sockaddr *) &client_address6, (void *) &address_length);
       +    }
       +    else
       +    {
       +#else
       +    if (1) {
       +#endif
       +        address_length = sizeof(client_address);
       +        connection_socket = accept(listen_socket, (struct sockaddr *) &client_address, (void *) &address_length);
       +    }
        
            struct timeval timeout;
            timeout.tv_sec = 5;
       @@ -153,7 +196,12 @@ void perform_connection(int listen_socket)
        
            struct thread_arguments arguments;
            arguments.connection_socket = connection_socket;
       -    arguments.client_address = client_address;
       +#if (HAVE_INET6)
       +    if (IPv6)
       +        arguments.client_address6 = client_address6;
       +    else
       +#endif
       +        arguments.client_address = client_address;
        
            if (pthread_create(&thread_id, NULL, &thread_connection, &arguments) != 0)
                error("on thread creation");
       @@ -202,6 +250,36 @@ struct client_data get_client_address(struct sockaddr_in client_address)
            return data;
        }
        
       +#if (HAVE_INET6)
       +struct client_data get_client_address6(struct sockaddr_in6 client_address6)
       +{
       +    struct hostent *hostp;
       +    struct client_data data;
       +    static char hostaddrp[INET6_ADDRSTRLEN];
       +
       +    hostp = gethostbyaddr((const char *)&client_address6.sin6_addr, sizeof(client_address6.sin6_addr), AF_INET6);
       +    if (hostp == NULL)
       +    {
       +        printf("WARNING: Couldn't obtain client's hostname\n");
       +        data.hostname = "n/a";
       +    }
       +    else
       +        data.hostname = hostp->h_name;
       +
       +    inet_ntop(AF_INET6, &(client_address6.sin6_addr), hostaddrp,
       +              INET6_ADDRSTRLEN);
       +    if (hostaddrp == NULL)
       +    {
       +        printf("WARNING: Couldn't obtain client's address\n");
       +        data.ip_address = "n/a";
       +    }
       +    else
       +        data.ip_address = hostaddrp;
       +
       +    return data;
       +}
       +#endif
       +
        void save_log(char *slug, char *hostaddrp, char *h_name)
        {
            if (LOG != NULL)
       @@ -275,7 +353,13 @@ void load_list(char *file_path, int type)
        
        int create_socket()
        {
       -    int lsocket = socket(AF_INET, SOCK_STREAM, 0);
       +    int lsocket;
       +#if (HAVE_INET6)
       +    if (IPv6)
       +        lsocket = socket(AF_INET6, SOCK_STREAM, 0);
       +    else
       +#endif
       +        lsocket = socket(AF_INET, SOCK_STREAM, 0);
        
            if (lsocket < 0)
                error("Couldn't open socket");
       @@ -292,6 +376,17 @@ struct sockaddr_in set_address(struct sockaddr_in server_address)
            return server_address;
        }
        
       +#if (HAVE_INET6)
       +struct sockaddr_in6 set_address6(struct sockaddr_in6 server_address6)
       +{
       +    bzero((char *) &server_address6, sizeof(server_address6));
       +    server_address6.sin6_family = AF_INET6;
       +    server_address6.sin6_addr = in6addr_any;
       +    server_address6.sin6_port = htons((unsigned short)PORT);
       +    return server_address6;
       +}
       +#endif
       +
        void bind_to_port(int listen_socket, struct sockaddr_in server_address)
        {
            if (bind(listen_socket, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) 
       @@ -300,6 +395,16 @@ void bind_to_port(int listen_socket, struct sockaddr_in server_address)
                error("while starting listening");
        }
        
       +#if (HAVE_INET6)
       +void bind_to_port6(int listen_socket, struct sockaddr_in6 server_address6)
       +{
       +    if (bind(listen_socket, (struct sockaddr *) &server_address6, sizeof(server_address6)) < 0) 
       +        error("while binding to port");
       +    if (listen(listen_socket, QUEUE_SIZE) < 0)
       +        error("while starting listening");
       +}
       +#endif
       +
        void generate_url(char *buffer, char *slug, size_t slug_length, struct client_data data)
        {
            int i;
       @@ -419,12 +524,15 @@ void parse_parameters(int argc, char **argv)
        {
            int c;
        
       -    while ((c = getopt (argc, argv, "DeSp:b:s:d:o:l:B:u:w:")) != -1)
       +    while ((c = getopt (argc, argv, "D6eSp:b:s:d:o:l:B:u:w:")) != -1)
                switch (c)
                {
                    case 'D':
                        DAEMON = 1;
                        break;
       +            case '6':
       +                IPv6 = 1;
       +                break;
                    case 'e':
                        snprintf(symbols, sizeof symbols, "%s", "abcdefghijklmnopqrstuvwxyz0123456789-+_=.ABCDEFGHIJKLMNOPQRSTUVWXYZ");
                        break;
       @@ -461,7 +569,7 @@ void parse_parameters(int argc, char **argv)
                        load_list(WHITEFILE, 1);
                        break;
                    default:
       -                printf("usage: fiche [-pbsdSolBuw].\n");
       +                printf("usage: fiche [-D6epbsdSolBuw].\n");
                        printf("                     [-d domain] [-p port] [-s slug_size]\n");
                        printf("                     [-o output directory] [-B buffer_size] [-u user name]\n");
                        printf("                     [-l log file] [-b banlist] [-w whitelist]\n");
 (DIR) diff --git a/fiche.h b/fiche.h
       @@ -31,6 +31,10 @@ $ cat fiche.c | nc localhost 9999
        #ifndef FICHE_H
        #define FICHE_H
        
       +#ifndef HAVE_INET6
       +#define HAVE_INET6 1
       +#endif
       +
        #include <pwd.h>
        #include <time.h>
        #include <netdb.h>
       @@ -56,6 +60,7 @@ char *WHITELIST;
        int DAEMON = 0;
        int HTTPS = 0;
        int PORT = 9999;
       +int IPv6 = 0;
        int SLUG_SIZE = 4;
        int BUFSIZE = 32768;
        int QUEUE_SIZE = 500;
       @@ -68,6 +73,9 @@ struct thread_arguments
        {
                int connection_socket;
                struct sockaddr_in client_address;
       +#if (HAVE_INET6)
       +        struct sockaddr_in6 client_address6;
       +#endif
        };
        
        struct client_data
       @@ -81,6 +89,9 @@ int create_directory(char *slug);
        int check_protocol(char *buffer);
        
        void bind_to_port(int listen_socket, struct sockaddr_in serveraddr);
       +#if (HAVE_INET6)
       +void bind_to_port6(int listen_socket, struct sockaddr_in6 serveraddr6);
       +#endif
        void error(char *buffer);
        void perform_connection(int listen_socket);
        void generate_url(char *buffer, char *slug, size_t slug_length, struct client_data data);
       @@ -99,6 +110,12 @@ char *check_whitelist(char *ip_address);
        char *get_date();
        
        struct sockaddr_in set_address(struct sockaddr_in serveraddr);
       +#if (HAVE_INET6)
       +struct sockaddr_in6 set_address6(struct sockaddr_in6 serveraddr6);
       +#endif
        struct client_data get_client_address(struct sockaddr_in client_address);
       +#if (HAVE_INET6)
       +struct client_data get_client_address6(struct sockaddr_in6 client_address6);
       +#endif
        
        #endif