/* webdump6.c -- Copyright (C) 2001 Paul Stauffer * A primitive IPv6 HTTP client. Connects to the specified server on the * standard HTTP port, using the IPv6 protocol at the network layer, * requests a document, and dumps the resulting document to stdout. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #define INPUT_BUFSIZ BUFSIZ*10 #define MAXTRIES 3 #define TIMEOUT_SECS 20 #define TIMEOUT_USECS 0 int main(int argc, char* argv[]) { int s; /* socket descriptor */ int alen; /* length of an AF_INET6 address */ int offset = 0; /* memory offset */ int retval = 0; /* value returned by select */ int tries = 0; /* number of attempts to make */ /* Note that the default size of the input buffer will not actually accommodate the length of many modern web pages. For production purposes, increase this by a large multiplicative factor, but this will be good enough for demonstration purposes. */ char inbuf[INPUT_BUFSIZ]; /* input buffer */ char outbuf[BUFSIZ]; /* output buffer */ char* host; /* hostname of server */ char* url = "/index.html"; /* URL to request */ struct sockaddr_in6 saddr; /* socket structure */ struct hostent* servdata; /* data returned by gethostbyname */ fd_set readset; /* for select */ struct timeval timeout; /* timeout value waiting for server */ switch(argc) { case 3: url = argv[2]; host = argv[1]; break; case 2: host = argv[1]; break; default: fprintf(stderr, "usage: webdump host [url]\n"); return(1); } /* To be safe, zero out these items */ memset(inbuf, '\0', INPUT_BUFSIZ); memset(outbuf, '\0', BUFSIZ); memset(&saddr, 0, sizeof(saddr)); /* lookup host data */ if ((servdata = gethostbyname2(host, AF_INET6)) == NULL) { fprintf(stderr, "Error looking up host: %s\n", hstrerror(h_errno)); return(1); } /* set up the server address */ memcpy(&saddr.sin6_addr, servdata->h_addr, servdata->h_length); saddr.sin6_family = AF_INET6; saddr.sin6_port = htons(80); /* HTTP port, currently hard-coded */ alen = sizeof(saddr); /* create socket */ if ((s = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "Error creating socket\n"); return(1); } /* connect to server */ if ((connect(s, &saddr, alen)) < 0) { fprintf(stderr, "Error connecting to server: %s\n", strerror(errno)); close(s); return(1); } /* set up the request string */ strcat(outbuf, "GET "); strncat(outbuf, url, strlen(url)); strcat(outbuf, " HTTP/1.0\r\n\r\n"); while (retval == 0) { send(s, outbuf, strlen(outbuf), 0); /* set up for the select */ memset(&timeout, 0, sizeof(timeout)); timeout.tv_sec = TIMEOUT_SECS; timeout.tv_usec = TIMEOUT_USECS; FD_ZERO(&readset); FD_SET(s, &readset); if ((retval = select(s+1, &readset, NULL, NULL, &timeout)) < 0) { fprintf(stderr, "Error on select\n"); close(s); return(1); } else if (retval == 0) { tries++; fprintf(stderr, "Attempt %i timed out.\n", tries); if (tries == MAXTRIES) { fprintf(stderr, "Server not responding, giving up.\n"); close(s); return(1); } } } recv(s, inbuf, INPUT_BUFSIZ-1, 0); /* Step through the received buffer, looking for the byte pattern that indicates the end of the HTTP header. */ while(strncmp(inbuf+offset, "\r\n\r\n", 4) != 0) { offset++; } /* Anything other than "200" at this location indicates some sort of */ /* HTTP error */ if (strncmp(inbuf+9, "200", 3) != 0) { /* Set the next byte after the HTTP header to a NULL, so that */ /* output will stop when it gets to this point. */ memset(inbuf+offset+4, '\0', 1); fprintf(stdout, inbuf); /* Print the HTTP headers. */ close(s); return(1); } /* Print the response, starting 4 bytes after the location we identified as the beginning of the "\r\n\r\n" string. */ fprintf(stdout, inbuf+offset+4); close(s); return(0); }