blob: 6f2fa2dab1b7ab05c41b654d7d7ecbbb0c111930 [file] [log] [blame]
mridge949c5b12006-01-03 23:01:28 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
mridge949c5b12006-01-03 23:01:28 +000018 */
19
20/*
21 * Test Name: asapi_04
22 *
23 * Test Description:
24 * Verify that in6 and sockaddr fields are present. Most of these are
25 * "PASS" if they just compile.
26 *
27 * Usage: <for command-line>
28 * asapi_04
29 *
30 * HISTORY
31 * 04/2005 written by David L Stevens
32 *
33 * RESTRICTIONS:
34 * None.
35 *
36 */
37
38#include <stdio.h>
39#include <unistd.h>
40#include <errno.h>
41#include <netdb.h>
42#include <libgen.h>
43#include <pthread.h>
44#include <semaphore.h>
45
46#include <sys/time.h>
subrata_modak7fe64512008-12-12 13:41:11 +000047#include <sys/socket.h>
mridge949c5b12006-01-03 23:01:28 +000048#include <netinet/in.h>
mridge949c5b12006-01-03 23:01:28 +000049
50#include "test.h"
mridge949c5b12006-01-03 23:01:28 +000051
Wanlong Gao354ebb42012-12-07 10:10:04 +080052char *TCID = "asapi_04"; /* Test program identifier. */
mridge949c5b12006-01-03 23:01:28 +000053
54pid_t pid;
55
56struct {
Wanlong Gao354ebb42012-12-07 10:10:04 +080057 char *prt_name;
58 int prt_value;
mridge949c5b12006-01-03 23:01:28 +000059} ptab[] = {
Wanlong Gao354ebb42012-12-07 10:10:04 +080060 {
61 "hopopt", 0}, {
62 "ipv6", 41}, {
63 "ipv6-route", 43}, {
64 "ipv6-frag", 44}, {
65 "esp", 50}, {
66 "ah", 51}, {
67 "ipv6-icmp", 58}, {
68 "ipv6-nonxt", 59}, {
69"ipv6-opts", 60},};
mridge949c5b12006-01-03 23:01:28 +000070
mridge949c5b12006-01-03 23:01:28 +000071#define PTCOUNT (sizeof(ptab)/sizeof(ptab[0]))
72
73#define READ_TIMEOUT 5 /* secs */
74
75void do_tests(void);
76void setup(void), cleanup(void);
subrata_modakaa588ae2008-09-18 13:18:36 +000077int csum_test(char *rhost);
mridge949c5b12006-01-03 23:01:28 +000078
Wanlong Gao354ebb42012-12-07 10:10:04 +080079int main(int argc, char *argv[])
mridge949c5b12006-01-03 23:01:28 +000080{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020081 const char *msg;
mridge949c5b12006-01-03 23:01:28 +000082 int lc;
mridge949c5b12006-01-03 23:01:28 +000083
84 /* Parse standard options given to run the test. */
85 msg = parse_opts(argc, argv, 0, 0);
Garrett Cooperdf3eb162010-11-28 22:44:32 -080086 if (msg != NULL) {
Garrett Cooper53740502010-12-16 00:04:01 -080087 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
mridge949c5b12006-01-03 23:01:28 +000088 }
89
90 pid = getpid();
91
92 setup();
93
94 for (lc = 0; TEST_LOOPING(lc); ++lc)
95 do_tests();
96
97 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -080098
99 tst_exit();
100}
mridge949c5b12006-01-03 23:01:28 +0000101
Wanlong Gao354ebb42012-12-07 10:10:04 +0800102void do_tests(void)
mridge949c5b12006-01-03 23:01:28 +0000103{
104 int i;
105
106/* RFC 3542, Section 2.3 */
107#ifndef IN6_ARE_ADDR_EQUAL
108 tst_resm(TBROK, "IN6_ARE_ADDR_EQUAL not present");
109#else /* IN6_ARE_ADDR_EQUAL */
110 /*
111 * set each bit in an address and check for unequal; then set
112 * in the second address and check for equal. Covers all bits, all
113 * combinations.
114 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800115 {
116 struct in6_addr a1, a2;
117 int word, bit;
118 int rv = 1;
mridge949c5b12006-01-03 23:01:28 +0000119
120 memset(&a1, 0, sizeof(a1));
121 memset(&a2, 0, sizeof(a2));
122
123 rv = IN6_ARE_ADDR_EQUAL(&a1, &a2);
124
Wanlong Gao354ebb42012-12-07 10:10:04 +0800125 for (word = 0; word < 4; ++word)
126 for (bit = 0; bit < 32; ++bit) {
127 uint32_t newbit = 1 << bit;
mridge949c5b12006-01-03 23:01:28 +0000128
129 a1.s6_addr32[word] |= newbit; /* unequal */
130 rv &= !IN6_ARE_ADDR_EQUAL(&a1, &a2);
131 a2.s6_addr32[word] |= newbit; /* equal */
132 rv &= IN6_ARE_ADDR_EQUAL(&a1, &a2);
133 }
134 tst_resm(rv ? TPASS : TFAIL, "IN6_ARE_ADDR_EQUAL");
135 }
136#endif /* IN6_ARE_ADDR_EQUAL */
137
138/* RFC 3542, Section 2.4 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800139 for (i = 0; i < PTCOUNT; ++i) {
mridge949c5b12006-01-03 23:01:28 +0000140 struct protoent *pe;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141 int pass;
mridge949c5b12006-01-03 23:01:28 +0000142
143 pe = getprotobyname(ptab[i].prt_name);
144 pass = pe && pe->p_proto == ptab[i].prt_value;
145 tst_resm(pass ? TPASS : TFAIL, "\"%s\" protocols entry",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800146 ptab[i].prt_name);
mridge949c5b12006-01-03 23:01:28 +0000147 }
148/* RFC 3542, Section 3.1 */
149 csum_test("::1");
150}
151
152/*
153 * this next-header value shouldn't be a real protocol!!
154 * 0x9f = 01 0 11111
155 * | | |
156 * | | |--- rest- ~0
157 * | |--------- chg - "no change enroute"
158 * |----------- act - "discard unknown"
159 */
160#define NH_TEST 0x9f
161
162struct tprot {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800163 int tp_pid; /* sender PID */
164 int tp_seq; /* sequence # */
165 int tp_offset; /* offset of cksum */
166 int tp_dlen; /* tp_dat length */
167 unsigned char tp_dat[0]; /* user data */
mridge949c5b12006-01-03 23:01:28 +0000168};
169
170unsigned char tpbuf[sizeof(struct tprot) + 2048];
171unsigned char rpbuf[sizeof(struct tprot) + 2048];
172
173struct csent {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800174 int cs_offset;
175 int cs_dlen;
176 int cs_setresult; /* setsockopt expected result */
177 int cs_seterrno; /* setsockopt expected errno */
178 int cs_sndresult; /* send expected result */
179 int cs_snderrno; /* send expected errno */
mridge949c5b12006-01-03 23:01:28 +0000180} cstab[] = {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800181 {
182 0, 5, 0, 0, 0, 0}, {
183 6, 30, 0, 0, 0, 0}, {
184 3, 20, -1, EINVAL, -1, -1}, /* non-aligned offset */
185 {
186 4, 5, 0, 0, -1, EINVAL}, /* not enough space */
187 {
188 50, 5, 0, 0, -1, EINVAL}, /* outside of packet */
189 {
190 22, 30, 0, 0, 0, 0}, {
191 2000, 2004, 0, 0, 0, 0}, /* in a fragment (over Ethernet) */
mridge949c5b12006-01-03 23:01:28 +0000192};
193
194#define CSCOUNT (sizeof(cstab)/sizeof(cstab[0]))
195
subrata_modakaa588ae2008-09-18 13:18:36 +0000196static int recvtprot(int sd, unsigned char *packet, int psize)
mridge949c5b12006-01-03 23:01:28 +0000197{
198 struct tprot *tpt;
199 int cc, total, expected;
200 int gothead;
201
202 tpt = (struct tprot *)packet;
203 total = cc = recv(sd, packet, sizeof(struct tprot), 0);
204 expected = sizeof(struct tprot); /* until we get tp_dlen */
205 gothead = total >= sizeof(struct tprot);
206 if (gothead)
207 expected += ntohl(tpt->tp_dlen);
208 if (cc <= 0)
209 return cc;
210 while (cc > 0 && total < expected) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800211 cc = recv(sd, &packet[total], expected - total, 0);
mridge949c5b12006-01-03 23:01:28 +0000212 if (cc >= 0) {
213 total += cc;
214 if (!gothead && total >= sizeof(struct tprot)) {
215 gothead = 1;
216 expected += ntohl(tpt->tp_dlen);
217 }
218 } else
219 break;
220 }
221 if (cc < 0)
222 return cc;
223 return total;
224}
225
226unsigned short csum(unsigned short partial, unsigned char *packet, int len)
227{
228 unsigned long sum = partial;
229 unsigned short *ps;
230 int i;
231
232 ps = (unsigned short *)packet;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800233 for (i = 0; i < len / 2; ++i)
mridge949c5b12006-01-03 23:01:28 +0000234 sum += *ps++;
235 if (len & 1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800236 sum += htons(packet[len - 1] << 8);
mridge949c5b12006-01-03 23:01:28 +0000237 sum = (sum >> 16) + (sum & 0xffff);
238 sum += (sum >> 16);
239 return ~sum;
240}
241
242struct ph {
243 struct in6_addr ph_sa;
244 struct in6_addr ph_da;
245 uint32_t ph_len;
246 uint8_t ph_mbz[3];
247 uint8_t ph_nh;
248} ph;
249
subrata_modakaa588ae2008-09-18 13:18:36 +0000250static int client(int prot, int sfd)
mridge949c5b12006-01-03 23:01:28 +0000251{
252 struct tprot *pttp = (struct tprot *)tpbuf;
253 struct tprot *prtp = (struct tprot *)rpbuf;
254 struct sockaddr_in6 rsin6;
255 static int seq;
256 int i, sd, cc, cs;
257
258 memset(&rsin6, 0, sizeof(rsin6));
259 rsin6.sin6_family = AF_INET6;
260 rsin6.sin6_addr = in6addr_loopback;
261
262 memset(&ph, 0, sizeof(ph));
263 ph.ph_sa = rsin6.sin6_addr;
264 ph.ph_da = rsin6.sin6_addr;
265 ph.ph_nh = NH_TEST;
266
267 sd = socket(PF_INET6, SOCK_RAW, NH_TEST);
268 if (sd < 0) {
269 tst_resm(TBROK, "can't create raw socket: %s", strerror(errno));
270 return -1;
271 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800272 for (i = 0; i < CSCOUNT; ++i) {
mridge949c5b12006-01-03 23:01:28 +0000273 int offset, len, xlen;
subrata_modakaa588ae2008-09-18 13:18:36 +0000274 int rv;
mridge949c5b12006-01-03 23:01:28 +0000275 unsigned char *p, *pend;
276
277 offset = sizeof(struct tprot) + cstab[i].cs_offset;
278 len = sizeof(struct tprot) + cstab[i].cs_dlen;
279
280 memset(pttp, 0, sizeof(*pttp));
281 memset(pttp->tp_dat, 0xA5, cstab[i].cs_dlen);
282
283 pttp->tp_pid = htonl(pid);
284 pttp->tp_offset = ntohl(offset);
285 pttp->tp_dlen = ntohl(cstab[i].cs_dlen);
286 pttp->tp_seq = ntohl(++seq);
287
288 TEST(setsockopt(sd, IPPROTO_IPV6, IPV6_CHECKSUM, &offset,
289 sizeof(offset)));
290 if (TEST_RETURN != cstab[i].cs_setresult) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800291 tst_resm(TFAIL | TTERRNO,
292 "IPV6_CHECKSUM offset %d len %d "
293 "- result %ld != %d", offset, len, TEST_RETURN,
294 cstab[i].cs_setresult);
mridge949c5b12006-01-03 23:01:28 +0000295 continue;
296 }
297 if (TEST_RETURN < 0) {
298 tst_resm(TPASS, "IPV6_CHECKSUM offset %d len %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800299 offset, len);
mridge949c5b12006-01-03 23:01:28 +0000300 continue;
301 }
302 if (TEST_RETURN && TEST_ERRNO != cstab[i].cs_seterrno) {
303 tst_resm(TFAIL, "IPV6_CHECKSUM offset %d len %d "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800304 "- errno %d != %d", offset, len,
305 TEST_ERRNO, cstab[i].cs_seterrno);
mridge949c5b12006-01-03 23:01:28 +0000306 continue;
307 }
308 /* send packet */
309 TEST(sendto(sd, pttp, len, 0, (struct sockaddr *)&rsin6,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800310 sizeof(rsin6)));
mridge949c5b12006-01-03 23:01:28 +0000311 xlen = (cstab[i].cs_sndresult < 0) ? -1 : len;
312 if (TEST_RETURN != xlen) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800313 tst_resm(TFAIL | TTERRNO,
314 "IPV6_CHECKSUM offset %d len %d "
315 "- sndresult %ld != %d", offset, len,
316 TEST_RETURN, xlen);
mridge949c5b12006-01-03 23:01:28 +0000317 continue;
318 }
319 if (TEST_RETURN < 0 && TEST_ERRNO != cstab[i].cs_snderrno) {
320 tst_resm(TFAIL, "IPV6_CHECKSUM offset %d len %d "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800321 "- snderrno %d != %d", offset, len,
322 TEST_ERRNO, cstab[i].cs_snderrno);
mridge949c5b12006-01-03 23:01:28 +0000323 continue;
324 }
325 if (TEST_RETURN < 0) {
326 tst_resm(TPASS, "IPV6_CHECKSUM offset %d len %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800327 offset, len);
mridge949c5b12006-01-03 23:01:28 +0000328 continue;
329 }
subrata_modakaa588ae2008-09-18 13:18:36 +0000330 while ((cc = recvtprot(sfd, rpbuf, sizeof(rpbuf)))) {
mridge949c5b12006-01-03 23:01:28 +0000331 if (htonl(prtp->tp_pid) == pid &&
332 htonl(prtp->tp_seq) == seq)
333 break;
334 }
335 rv = 1;
336 pend = rpbuf + sizeof(struct tprot) + ntohl(prtp->tp_dlen);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800337 for (p = &prtp->tp_dat[0]; p < pend; ++p) {
338 if (p == &rpbuf[offset] || p == &rpbuf[offset + 1])
mridge949c5b12006-01-03 23:01:28 +0000339 continue;
340 if (*p != 0xa5) {
341 tst_resm(TFAIL, "IPV6_CHECKSUM corrupt data "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800342 "0x%02x != 0xa5 at offset %d in packet",
343 *p, p - rpbuf);
mridge949c5b12006-01-03 23:01:28 +0000344 rv = 0;
345 break;
346 }
347 }
348 if (rv == 0)
349 continue;
350 ph.ph_len = htonl(xlen);
351 cs = csum(0, (unsigned char *)&ph, sizeof(ph));
352 cs = csum(~cs, rpbuf, xlen);
353 if (!csum(0, rpbuf, xlen)) {
354 tst_resm(TFAIL, "IPV6_CHECKSUM offset %d len %d (bad "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800355 "checksum)", offset, len);
mridge949c5b12006-01-03 23:01:28 +0000356 continue;
357 }
358 tst_resm(TPASS, "IPV6_CHECKSUM offset %d len %d", offset, len);
359 }
subrata_modakaa588ae2008-09-18 13:18:36 +0000360 return 0;
mridge949c5b12006-01-03 23:01:28 +0000361}
362
363static int listen_fd, connect_fd;
364sem_t ilsem;
365
Wanlong Gao354ebb42012-12-07 10:10:04 +0800366void *ilistener(void *arg)
mridge949c5b12006-01-03 23:01:28 +0000367{
368 connect_fd = accept(listen_fd, 0, 0);
369 close(listen_fd);
370 sem_post(&ilsem);
subrata_modakaa588ae2008-09-18 13:18:36 +0000371 return NULL;
mridge949c5b12006-01-03 23:01:28 +0000372}
373
Wanlong Gao354ebb42012-12-07 10:10:04 +0800374int isocketpair(int pf, int type, int proto, int fd[2])
mridge949c5b12006-01-03 23:01:28 +0000375{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800376 pthread_t thid;
mridge949c5b12006-01-03 23:01:28 +0000377 struct sockaddr_in sin4;
subrata_modakaa588ae2008-09-18 13:18:36 +0000378 socklen_t namelen;
mridge949c5b12006-01-03 23:01:28 +0000379
380/* restrict to PF_INET for now */
381 if (pf != PF_INET) {
382 errno = EOPNOTSUPP;
383 return -1;
384 }
385 sem_init(&ilsem, 0, 0);
386 listen_fd = socket(pf, type, proto);
387 if (listen_fd < 0) {
388 perror("socket");
389 return -1;
390 }
391 memset(&sin4, 0, sizeof(sin4));
392 if (bind(listen_fd, (struct sockaddr *)&sin4, sizeof(sin4)) < 0) {
393 perror("bind");
394 return -1;
395 }
396 if (listen(listen_fd, 10) < 0) {
397 perror("listen");
398 return -1;
399 }
400 namelen = sizeof(sin4);
401 if (getsockname(listen_fd, (struct sockaddr *)&sin4, &namelen) < 0) {
402 perror("getsockname");
403 return -1;
404 }
405 if (pthread_create(&thid, 0, ilistener, 0) < 0) {
406 perror("pthread_create");
407 return -1;
408 }
409
410 fd[0] = socket(pf, type, proto);
411 if (fd[0] < 0) {
412 perror("socket");
413 return -1;
414 }
415 sin4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
416 if (connect(fd[0], (struct sockaddr *)&sin4, sizeof(sin4)) < 0) {
417 perror("connect");
418 return -1;
419 }
420 sem_wait(&ilsem);
421 fd[1] = connect_fd;
422 sem_destroy(&ilsem);
423 return 0;
424}
425
426#ifndef MAX
427#define MAX(a, b) ((a) >= (b) ? (a) : (b))
428#endif /* MAX */
429
Wanlong Gao354ebb42012-12-07 10:10:04 +0800430int csum_test(char *rhost)
mridge949c5b12006-01-03 23:01:28 +0000431{
432 fd_set rset, rset_save;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800433 int csd[2]; /* control sockets */
mridge949c5b12006-01-03 23:01:28 +0000434 int sd, nfds, maxfd, cc;
435 struct timeval tv;
436
437/* rhost == loopback, for now */
438 if (strcmp(rhost, "::1")) {
439 tst_resm(TBROK, "invalid rhost \"%s\"", rhost);
440 return -1;
441 }
442 if (isocketpair(PF_INET, SOCK_STREAM, 0, csd) < 0) {
443 tst_resm(TBROK, "socketpair: %s", strerror(errno));
444 return -1;
445 }
446 sd = socket(PF_INET6, SOCK_RAW, NH_TEST);
447 if (sd < 0) {
448 int saved_errno = errno;
449
450 if (errno == EPERM && geteuid())
451 tst_resm(TBROK, "IPV6_CHECKSUM tests must run as root");
452 else
453 tst_resm(TBROK, "All IPv6_CHECKSUM tests broken: "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800454 "socket: %s", strerror(saved_errno));
mridge949c5b12006-01-03 23:01:28 +0000455 return -1;
456 }
457 FD_ZERO(&rset_save);
458 FD_SET(sd, &rset_save);
459 FD_SET(csd[1], &rset_save);
460 memcpy(&rset, &rset_save, sizeof(rset));
461 maxfd = MAX(sd, csd[1]);
462
463 /* server socket set; now start the client */
464 switch (fork()) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800465 case 0: /* child */
mridge949c5b12006-01-03 23:01:28 +0000466 close(csd[0]);
467 break;
468 case -1:
469 tst_resm(TBROK, "can't fork rserver");
470 return -1;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800471 default: /* parent */
mridge949c5b12006-01-03 23:01:28 +0000472 close(sd);
473 close(csd[1]);
474 return client(pid, csd[0]);
475 }
476
477 tv.tv_sec = READ_TIMEOUT;
478 tv.tv_usec = 0;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800479 while ((nfds = select(maxfd + 1, &rset, 0, 0, &tv)) >= 0) {
mridge949c5b12006-01-03 23:01:28 +0000480 if (nfds < 0) {
481 if (errno == EINTR)
482 continue;
483 exit(0);
484 } else if (nfds == 0) {
485 fprintf(stderr, "server read timed out");
486 return -1;
487 }
488 if (FD_ISSET(sd, &rset)) {
489 static char packet[2048];
490
Wanlong Gao354ebb42012-12-07 10:10:04 +0800491 cc = recv(sd, packet, sizeof(packet), 0);
mridge949c5b12006-01-03 23:01:28 +0000492 if (cc < 0) {
493 perror("server recvtprot");
494 exit(1);
495 }
496 if (cc == 0)
497 exit(0);
498 if (write(csd[1], packet, cc) < 0) {
499 perror("server write UNIX socket");
500 exit(0);
501 }
502 }
503 if (FD_ISSET(csd[1], &rset)) {
504 char buf[2048];
505
506 cc = read(csd[1], buf, sizeof(buf));
507 if (cc == 0) {
508 exit(0);
509 }
510 if (cc < 0) {
511 perror("server read");
512 exit(1);
513 }
514 /* handle commands here, if any added later */
515 }
516 memcpy(&rset, &rset_save, sizeof(rset));
517 tv.tv_sec = READ_TIMEOUT;
518 tv.tv_usec = 0;
519 }
subrata_modakaa588ae2008-09-18 13:18:36 +0000520 return 0;
mridge949c5b12006-01-03 23:01:28 +0000521}
522
Wanlong Gao354ebb42012-12-07 10:10:04 +0800523void setup(void)
mridge949c5b12006-01-03 23:01:28 +0000524{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800525 TEST_PAUSE; /* if -P option specified */
mridge949c5b12006-01-03 23:01:28 +0000526}
527
Wanlong Gao354ebb42012-12-07 10:10:04 +0800528void cleanup(void)
mridge949c5b12006-01-03 23:01:28 +0000529{
mridge949c5b12006-01-03 23:01:28 +0000530}
531
Chris Dearmanec6edca2012-10-17 19:54:01 -0700532int TST_TOTAL = PTCOUNT + CSCOUNT;