lkml.org 
[lkml]   [2002]   [Jul]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: more thoughts on a new jail() system call
    Hi,

    On 19 Jul 2002, James Antill wrote:
    > The more general spelling is FIONREAD, and I generally find that only
    > crap network applications need to use it. Good ones just try and read
    > a largish amount of data into a buffer.

    That doesn't matter as long as you haven't got any idea on how much data
    will be read. Especially relaying between two completely different hosts,
    possibly unknown protocols, you don't have a chance to know who will send
    next. Without TIOCINQ you'll almost be shot if you have received lots of
    lots of stuff from the client and expect any response from the server. You
    just won't get it.

    Give me another version of the appended piece of code that won't use
    ioctl, and I'll consider an acknowledgement.

    Regards,
    Thunder
    --
    (Use http://www.ebb.org/ungeek if you can't decode)
    ------BEGIN GEEK CODE BLOCK------
    Version: 3.12
    GCS/E/G/S/AT d- s++:-- a? C++$ ULAVHI++++$ P++$ L++++(+++++)$ E W-$
    N--- o? K? w-- O- M V$ PS+ PE- Y- PGP+ t+ 5+ X+ R- !tv b++ DI? !D G
    e++++ h* r--- y-
    ------END GEEK CODE BLOCK------
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/ioctl.h>
    #include <netinet/in.h>
    #include <sys/socket.h>

    #define _perror(s) perror(s); errno = 0
    #define _probably_perror(s) if (errno) { perror(s); errno = 0; }

    unsigned short portfrom, portto;
    int sock, client, server, peer_size;
    struct sockaddr_in *local, *peer, *remote;
    char *buffer;

    int main(int argc, char **argv) {
    buffer = malloc(65537);
    remote = malloc(sizeof(struct sockaddr_in));
    local = malloc(sizeof(struct sockaddr_in));
    peer = malloc(sizeof(struct sockaddr_in));
    peer_size = sizeof(struct sockaddr_in);
    portfrom = 26;
    portto = 25;

    if (argc >= 3) {
    portfrom = (short)(atol(argv[1]) & 0xFFFF);
    portto = (short)(atol(argv[2]) & 0xFFFF);
    }

    local->sin_family = AF_INET;
    local->sin_port = htons(portfrom);
    local->sin_addr.s_addr = htonl(INADDR_ANY);

    remote->sin_family = AF_INET;
    remote->sin_port = htons(portto);
    remote->sin_addr.s_addr = inet_addr("192.168.1.1");

    printf("Target address: %i.%i.%i.%i:%i\n",
    remote->sin_addr.s_addr & 0xFF,
    (remote->sin_addr.s_addr >> 8) & 0xFF,
    (remote->sin_addr.s_addr >> 16) & 0xFF,
    (remote->sin_addr.s_addr >> 24) & 0xFF,
    ntohs(remote->sin_port));

    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == -1) {
    _perror("socket (controller)");
    exit(1);
    }
    if (bind(sock, (struct sockaddr *)local,
    sizeof(struct sockaddr_in)) < 0) {
    _perror("bind");
    exit(1);
    }
    if (listen(sock, 10) < 0) {
    _perror("listen");
    exit(1);
    }
    while ((client = accept(sock, (struct sockaddr *)peer,
    &peer_size)) >= 0) {
    unsigned long s;
    int in_recvq, overhead = 0, nr_loops = 0;

    for (s = 0; s < 65536; s++)
    buffer[s] = 0;

    printf("Connection from %s:%i\n",
    inet_ntoa(peer->sin_addr),
    ntohs(peer->sin_port));

    server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server == -1) {
    _perror("socket (server)");
    exit(1);
    }
    if (connect(server, (struct sockaddr *)remote,
    sizeof(struct sockaddr_in)) < 0) {
    _perror("connect (server)");
    goto out;
    }

    printf("Server connection is up.\n");
    usleep(100);

    if (ioctl(server, TIOCINQ, &in_recvq) != 0) {
    _perror("TIOCINQ (server)");
    goto out;
    }

    data_waiting:
    if (overhead - nr_loops >= 100)
    goto out;

    while (in_recvq) {
    nr_loops++;
    overhead = nr_loops;
    for (s = 0; s < 65536; s++)
    buffer[s] = 0;

    if (recv(server,buffer, 65535, 0) < 0) {
    _perror("recv (server)");
    goto out;
    }
    printf("%s", buffer);
    if (send(client, buffer, strlen(buffer), 0) < 0) {
    _perror("send (server)");
    goto out;
    }
    if (ioctl(server, TIOCINQ, &in_recvq) != 0) {
    _perror("TIOCINQ (server)");
    goto out;
    }
    }

    if (ioctl(client, TIOCINQ, &in_recvq) != 0) {
    _perror("TIOCINQ (client)");
    goto out;
    }

    while (in_recvq) {
    nr_loops++;
    overhead = nr_loops;
    for (s = 0; s < 65536; s++)
    buffer[s] = 0;

    if (recv(client, buffer, 65535, 0) < 0) {
    _perror("recv (client)");
    goto out;
    }
    printf("%s", buffer);
    if (send(server, buffer, strlen(buffer), 0) < 0) {
    _perror("send (server)");
    goto out;
    }
    if (ioctl(client, TIOCINQ, &in_recvq) != 0) {
    _perror("TIOCINQ (client)");
    goto out;
    }
    }

    if (ioctl(server, TIOCINQ, &in_recvq) != 0) {
    _perror("TIOCINQ (server)");
    goto out;
    }

    overhead++;

    usleep(100);
    goto data_waiting;
    out:
    printf("Connection closing.\n");
    shutdown(client, SHUT_RDWR);
    _probably_perror("shutdown (client)");
    shutdown(server, SHUT_RDWR);
    _probably_perror("shutdown (server)");
    close(client);
    _probably_perror("close (client)");
    close(server);
    _probably_perror("close (server)");
    }

    if (close(sock)) {
    _perror("close (controller)");
    }

    exit(0);
    }

    /*
    * Local variables:
    * compile-command: "gcc -W -Wall -Os -o pf portforwarder.c"
    * c-basic-offset: 8
    * End:
    */
    \
     
     \ /
      Last update: 2005-03-22 13:27    [W:4.032 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site