Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

t_sockaddr_fcns.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2005 by Kevin L. Mitchell <klmitch@mit.edu>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 **
00018 ** @(#)$Id: t_sockaddr_fcns.c,v 1.1 2005/12/23 04:07:10 klmitch Exp $
00019 */
00029 #include "event-test.h"
00030 
00031 #include <netinet/in.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <sys/socket.h>
00036 #include <sys/types.h>
00037 #include <sys/un.h>
00038 
00039 RCSTAG("@(#)$Id: t_sockaddr_fcns.c,v 1.1 2005/12/23 04:07:10 klmitch Exp $");
00040 
00041 TEST_PROG(t_sockaddr_fcns, "Test operation of socket address "
00042           "manipulation functions")
00043      TEST_ARG(t_sockaddr_fcns, "<t_sockaddr_fcns.addrs>")
00044      TEST_DEP(t_sockaddr_fcns, t_event_log)
00045 
00055 unsigned int
00056 value(const char *str)
00057 {
00058   int i;
00059   struct {
00060     const char *name;
00061     unsigned int value;
00062   } map[] = {
00063     { "SUCCESS", 0 }, /* error codes */
00064     { "EINVAL", EINVAL },
00065     { "ADDRTOOLONG", EV_ERR_ADDRTOOLONG },
00066     { "ADDRINCOMPLETE", EV_ERR_ADDRINCOMPLETE },
00067     { "INVALIDCHAR", EV_ERR_INVALIDCHAR },
00068     { "COLONEXPECTED", EV_ERR_COLONEXPECTED },
00069     { "BADADDR", EV_ERR_BADADDR },
00070     { "NONE", AT_NONE }, /* address types */
00071     { "LOCAL", AT_LOCAL },
00072     { "IP4", AT_IPv4 },
00073     { "IP6", AT_IPv6 },
00074     { 0, 0 }
00075   };
00076 
00077   for (i = 0; map[i].name; i++) /* Search the name map */
00078     if (!strcmp(map[i].name, str))
00079       return map[i].value; /* found it, return the value */
00080 
00081   return 0;
00082 }
00083 
00090 int
00091 main(int argc, char **argv)
00092 {
00093   const char *ta = "/this/is/an/improbable/address";
00094   char *prog;
00095   ev_err_t err;
00096   ev_sockaddr_t addr;
00097   int len;
00098 
00099   ev_test_init(t_sockaddr_fcns); /* initialize test program */
00100   ev_prog_name(prog, argv);
00101 
00102   /* Clear the socket addresses... */
00103   memset(&addr, 0, sizeof(addr));
00104 
00105   /***************************************************************************
00106    * First task: Test the sa_* functions.                                    *
00107    ***************************************************************************/
00108 
00109   /* Begin with AT_NONE--all except sa_type_set() should fail */
00110   TEST(t_sockaddr_fcns, sa_none, "Test that AT_NONE addresses are rejected "
00111        "by all sa_* functions except sa_type_set()",
00112        (!(err = sa_type_set(&addr, AT_NONE)) && sa_type(&addr) == AT_NONE &&
00113         sa_ipaddrbuf_set(&addr, ta) == EINVAL &&
00114         sa_ipaddrport_set(&addr, 1234) == EINVAL &&
00115         sa_localaddr_set(&addr, ta) == EINVAL), 0,
00116        ("sa_type_set() properly set AT_NONE address type and other sa_* "
00117         "functions rejected it"),
00118        ("sa_type_set() failed to properly set AT_NONE address type or another "
00119         "sa_* function failed to reject it; error code %u, address type %u",
00120         err, sa_type(&addr)));
00121 
00122   /* Now, try AT_IPv4--before AT_IPv6, note. */
00123   TEST(t_sockaddr_fcns, sa_ipv4, "Test that sa_* functions handle IPv4 "
00124        "addresses properly",
00125        (!(err = sa_type_set(&addr, AT_IPv4)) && sa_type(&addr) == AT_IPv4 &&
00126         !(err = sa_ipaddrbuf_set(&addr, ta)) &&
00127         !(err = sa_ipaddrport_set(&addr, 1234)) &&
00128         !memcmp(sa_ipaddrbuf(&addr), ta, SOCK_ADDRBUFV4_LEN) &&
00129         sa_ipaddrbuf(&addr)[SOCK_ADDRBUFV4_LEN] == '\0' &&
00130         sa_ipaddrport(&addr) == 1234 &&
00131         sa_localaddr_set(&addr, ta) == EINVAL), 0,
00132        ("sa_* functions handle IPv4 addresses properly"),
00133        ("sa_* functions fail to handle IPv4 addresses properly; error "
00134         "code %u, address type %u", err, sa_type(&addr)));
00135 
00136   /* Next, let's try an AT_IPv6 address */
00137   TEST(t_sockaddr_fcns, sa_ipv6, "Test that sa_* functions handle IPv6 "
00138        "addresses properly",
00139        (!(err = sa_type_set(&addr, AT_IPv6)) && sa_type(&addr) == AT_IPv6 &&
00140         !(err = sa_ipaddrbuf_set(&addr, ta)) &&
00141         !(err = sa_ipaddrport_set(&addr, 0)) &&
00142         !memcmp(sa_ipaddrbuf(&addr), ta, SOCK_ADDRBUFV6_LEN) &&
00143         /* Note that the memset() above enables this even in the case of
00144          * structure padding.  We have to set the port to 0 for the no-
00145          * padding case in order to make this work.
00146          */
00147         sa_ipaddrbuf(&addr)[SOCK_ADDRBUFV6_LEN] == '\0' &&
00148         sa_ipaddrport(&addr) == 0 &&
00149         sa_localaddr_set(&addr, ta) == EINVAL), 0,
00150        ("sa_* functions handle IPv6 addresses properly"),
00151        ("sa_* functions fail to handle IPv6 addresses properly; error "
00152         "code %u, address type %u", err, sa_type(&addr)));
00153 
00154   /* Finally, let's try an AT_LOCAL address */
00155   TEST(t_sockaddr_fcns, sa_local, "Test that sa_* functions handle local "
00156        "addresses properly",
00157        (!(err = sa_type_set(&addr, AT_LOCAL)) && sa_type(&addr) == AT_LOCAL &&
00158         sa_ipaddrbuf_set(&addr, ta) == EINVAL &&
00159         sa_ipaddrport_set(&addr, 1234) == EINVAL &&
00160         !(err = sa_localaddr_set(&addr, ta)) &&
00161         !strcmp(sa_localaddr(&addr), ta)), 0,
00162        ("sa_* functions handle local addresses properly"),
00163        ("sa_* functions fail to handle local addresses properly; error "
00164         "code %u, address type %u", err, sa_type(&addr)));
00165 
00166   /***************************************************************************
00167    * Next: Test sockaddr_import() and sockaddr_export()                      *
00168    ***************************************************************************/
00169 
00170   TEST_DECL(t_sockaddr_fcns, sockaddr_import,
00171             "Test that sockaddr_import() can import socket address structures")
00172   TEST_DECL(t_sockaddr_fcns, sockaddr_export,
00173             "Test that sockaddr_export() can export socket address structures")
00174     do { /* allow us to break out of this test...and groups tests visually */
00175       struct sockaddr_un sun_in, sun_out;
00176       struct sockaddr_in sin_in, sin_out;
00177 #ifdef HAVE_SOCKADDR_IN6
00178       struct sockaddr_in6 sin6_in, sin6_out;
00179 #endif /* HAVE_SOCKADDR_IN6 */
00180 
00181       /* Clearing the socket address structures should allow memcmp() tests */
00182       memset(&sun_in, 0, sizeof(sun_in));
00183       memset(&sun_out, 0, sizeof(sun_out));
00184       memset(&sin_in, 0, sizeof(sin_in));
00185       memset(&sin_out, 0, sizeof(sin_out));
00186 #ifdef HAVE_SOCKADDR_IN6
00187       memset(&sin6_in, 0, sizeof(sin6_in));
00188       memset(&sin6_out, 0, sizeof(sin6_out));
00189 #endif /* HAVE_SOCKADDR_IN6 */
00190 
00191       /* start with a test of AT_LOCAL--that's simple... */
00192       sun_in.sun_family = AF_LOCAL;
00193       strcpy(sun_in.sun_path, ta); /* copy the local address over */
00194 
00195       /* Try an import */
00196       if ((err = sockaddr_import(&addr, (struct sockaddr *)&sun_in)) ||
00197           sa_type(&addr) != AT_LOCAL || strcmp(ta, sa_localaddr(&addr))) {
00198         FAIL(TEST_NAME(sockaddr_import), 0,
00199              "sockaddr_import() failed to import an AT_LOCAL address; "
00200              "error code %u, address type %u", err, sa_type(&addr));
00201         break; /* move on with the rest of the tests */
00202       }
00203 
00204       /* Next, try an export */
00205       len = sizeof(sun_out);
00206       if ((err = sockaddr_export(&addr, (struct sockaddr *)&sun_out, &len)) ||
00207           len != (sizeof(sun_out) - SOCK_LOCALADDR_LEN + strlen(ta)) ||
00208           memcmp(&sun_in, &sun_out, sizeof(sun_out))) {
00209         FAIL(TEST_NAME(sockaddr_export), 0,
00210              "sockaddr_export() failed to export an AT_LOCAL address; "
00211              "error code %u", err);
00212         break; /* move on with the rest of the tests */
00213       }
00214 
00215       /* Now, let's try an IPv4 address... */
00216       sin_in.sin_family = AF_INET;
00217       memcpy(&sin_in.sin_addr, ta, SOCK_ADDRBUFV4_LEN);
00218       sin_in.sin_port = htons(1234); /* have to be able to test port # */
00219 
00220       /* Try an import */
00221       if ((err = sockaddr_import(&addr, (struct sockaddr *)&sin_in)) ||
00222           sa_type(&addr) != AT_IPv4 ||
00223           memcmp(ta, sa_ipaddrbuf(&addr), SOCK_ADDRBUFV4_LEN) ||
00224           sa_ipaddrport(&addr) != 1234) {
00225         FAIL(TEST_NAME(sockaddr_import), 0,
00226              "sockaddr_import() failed to import an AT_IPv4 address; "
00227              "error code %u, address type %u", err, sa_type(&addr));
00228         break; /* move on with the rest of the tests */
00229       }
00230 
00231       /* Next, try an export */
00232       len = sizeof(sin_out);
00233       if ((err = sockaddr_export(&addr, (struct sockaddr *)&sin_out, &len)) ||
00234           len != sizeof(sin_out) || memcmp(&sin_in, &sin_out, len)) {
00235         FAIL(TEST_NAME(sockaddr_export), 0,
00236              "sockaddr_export() failed to export an AT_IPv4 address; "
00237              "error code %u", err);
00238         break; /* move on with the rest of the tests */
00239       }
00240 
00241 #ifdef HAVE_SOCKADDR_IN6
00242       /* Finally, let's try an IPv6 address... */
00243       sin6_in.sin6_family = AF_INET6;
00244       memcpy(&sin6_in.sin6_addr, ta, SOCK_ADDRBUFV6_LEN);
00245       sin6_in.sin6_port = htons(1234); /* have to be able to test port # */
00246 
00247       /* Try an import */
00248       if ((err = sockaddr_import(&addr, (struct sockaddr *)&sin6_in)) ||
00249           sa_type(&addr) != AT_IPv6 ||
00250           memcmp(ta, sa_ipaddrbuf(&addr), SOCK_ADDRBUFV6_LEN) ||
00251           sa_ipaddrport(&addr) != 1234) {
00252         FAIL(TEST_NAME(sockaddr_import), 0,
00253              "sockaddr_import() failed to import an AT_IPv6 address; "
00254              "error code %u, address type %u", err, sa_type(&addr));
00255         break; /* move on with the rest of the tests */
00256       }
00257 
00258       /* Next, try an export */
00259       len = sizeof(sin6_out);
00260       if ((err = sockaddr_export(&addr, (struct sockaddr *)&sin6_out, &len)) ||
00261           len != sizeof(sin6_out) || memcmp(&sin6_in, &sin6_out, len)) {
00262         FAIL(TEST_NAME(sockaddr_export), 0,
00263              "sockaddr_export() failed to export an AT_IPv6 address; "
00264              "error code %u", err);
00265         break; /* move on with the rest of the tests */
00266       }
00267 #endif /* HAVE_SOCKADDR_IN6 */
00268 
00269       /* Tests have been passed */
00270       PASS(TEST_NAME(sockaddr_import),
00271            "sockaddr_import() successfully imported socket addresses");
00272       PASS(TEST_NAME(sockaddr_export),
00273            "sockaddr_export() successfully exported socket addresses");
00274     } while (0);
00275 
00276   /***************************************************************************
00277    * Finally: Test sockaddr_ptoa() and sockaddr_atop()                       *
00278    ***************************************************************************/
00279 
00280   TEST_DECL(t_sockaddr_fcns, sockaddr_ptoa,
00281             "Test that sockaddr_ptoa() can process socket addresses")
00282   TEST_DECL(t_sockaddr_fcns, sockaddr_atop,
00283             "Test that sockaddr_atop() can display socket addresses")
00284     {
00285       char buf[512], presbuf[512], *t;
00286       unsigned char addrbuf[SOCK_LOCALADDR_LEN];
00287       ev_err_t exp;
00288       ev_satype_t type;
00289       int len, port;
00290       FILE *df;
00291 
00292       /* Just skip the tests if the data file isn't available */
00293       if (argc < 2 || !(df = fopen(argv[1], "r")))
00294         return 0;
00295 
00296       /* read the data file... */
00297       while ((t = fgets(buf, sizeof(buf), df))) {
00298         if ((t = strchr(buf, '\r')) || (t = strchr(buf, '\n')))
00299           *t = '\0'; /* chomp newline... */
00300 
00301         if (buf[0] == '#' || !(t = strtok(buf, " \t")))
00302           continue; /* skip empty lines and comments */
00303 
00304         exp = value(t); /* what's the expected return value? */
00305 
00306         if (!(t = strtok(0, " \t"))) { /* er... */
00307           fprintf(stderr, "%s: Expected IP address reading datafile %s\n",
00308                   prog, argv[1]);
00309           continue; /* skip the bogus line */
00310         }
00311 
00312         /* OK, let's try to parse it... */
00313         if ((err = sockaddr_ptoa(&addr, t, -1)) != exp)
00314           FAIL(TEST_NAME(sockaddr_ptoa), FATAL(0),
00315                "sockaddr_ptoa() failed with unexpected error %u (expected %u)",
00316                err, exp);
00317 
00318         if (exp || /* expected failure, go on to next test input */
00319             !(t = strtok(0, " \t"))) /* er, no verification data */
00320           continue;
00321 
00322         if (sa_type(&addr) != (type = value(t)))
00323           FAIL(TEST_NAME(sockaddr_ptoa), FATAL(0),
00324                "sockaddr_ptoa() parsed address type %u (expected %u)",
00325                sa_type(&addr), type);
00326 
00327         if (!(t = strtok(0, " \t"))) /* grab the address contents... */
00328           continue; /* no contents, just skip it */
00329 
00330         if (type == AT_LOCAL) { /* it's a local address */
00331           if (strcmp(sa_localaddr(&addr), t)) /* compare to what we got */
00332             FAIL(TEST_NAME(sockaddr_ptoa), FATAL(0),
00333                  "sockaddr_ptoa() parsed incorrect address: \"%s\" "
00334                  "(expected \"%s\")", sa_localaddr(&addr), t);
00335         } else { /* IP address, have to decode it */
00336           port = -1; /* initialize... */
00337           memset(addrbuf, 0, sizeof(addrbuf));
00338 
00339           /* decode the IP address... */
00340           for (len = 0; *t && *t; t++, len++)
00341             if (*t >= '0' && *t <= '9')
00342               addrbuf[len >> 1] |= (*t - '0') << (!(len & 0x01) << 2);
00343             else if (*t >= 'a' && *t <= 'f')
00344               addrbuf[len >> 1] |= (*t - 'a' + 0x0a) << (!(len & 0x01) << 2);
00345             else
00346               break; /* unrecognized character */
00347 
00348           if (*t == ':') /* got a port number specification */
00349             port = atoi(t + 1); /* convert it */
00350           else if (*t) {
00351             fprintf(stderr, "%s: Invalid character in address string: %c\n",
00352                     prog, *t);
00353             continue; /* skip this line */
00354           }
00355 
00356           if (memcmp(sa_ipaddrbuf(&addr), addrbuf, len >> 1) ||
00357               (port > 0 && sa_ipaddrport(&addr) != port))
00358             FAIL(TEST_NAME(sockaddr_ptoa), FATAL(0),
00359                  "sockaddr_ptoa() parsed incorrect address or port");
00360         }
00361 
00362         if (!(t = strtok(0, " \t"))) /* how about a presentation string? */
00363           continue; /* nothing there, just move on */
00364 
00365         /* try sockaddr_atop()... */
00366         presbuf[0] = '\0';
00367         if ((err = sockaddr_atop(&addr, presbuf, sizeof(presbuf), 0)) ||
00368             strcmp(presbuf, t))
00369           FAIL(TEST_NAME(sockaddr_atop), FATAL(0),
00370                "sockaddr_atop() failed or incorrectly formatted address; "
00371                "error code %u; expected: \"%s\"; got: \"%s\"", err, t,
00372                presbuf);
00373 
00374         /* Informational message */
00375         fprintf(stderr, "%s: INFO: Address formats to: \"%s\"\n", prog,
00376                 presbuf);
00377       }
00378 
00379       /* All tests passed! */
00380       PASS(TEST_NAME(sockaddr_ptoa),
00381            "sockaddr_ptoa() correctly parsed addresses");
00382       PASS(TEST_NAME(sockaddr_atop),
00383            "sockaddr_atop() correctly formatted addresses");
00384 
00385       fclose(df); /* close the data file */
00386     }
00387 
00388   return 0;
00389 }

Generated on Wed Dec 28 23:36:56 2005 for event by  doxygen 1.4.4