socktest.c revision 3f61fb90d08d4848a7d7dd24180c2b95ebd60bfc
1b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly/*
2b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** Copyright 2009 The Android Open Source Project
3b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly**
4b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** Licensed under the Apache License, Version 2.0 (the "License");
5b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** you may not use this file except in compliance with the License.
6b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** You may obtain a copy of the License at
7b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly**
8b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly**     http://www.apache.org/licenses/LICENSE-2.0
9b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly**
10b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** Unless required by applicable law or agreed to in writing, software
11b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** distributed under the License is distributed on an "AS IS" BASIS,
12b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** See the License for the specific language governing permissions and
14b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** limitations under the License.
15b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly*/
16b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
17b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly/** socket testing  */
18b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
19b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <stdlib.h>
20b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <stdio.h>
21b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <errno.h>
22b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <sys/uio.h>
23b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <unistd.h>
24b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
25b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <pthread.h>
26b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <stdio.h>
27b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <stdlib.h>
28b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <errno.h>
29b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <unistd.h>
30b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <sys/socket.h>
31b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <sys/ioctl.h>
32b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <sys/un.h>
33b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <netinet/in.h>
34b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
35b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <bluetooth/bluetooth.h>
36b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <bluetooth/rfcomm.h>
37b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <bluetooth/sco.h>
38b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <bluetooth/l2cap.h>
39b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
40b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellyenum sock_type {
41b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    UNIX = 0,
42b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    RFCOMM,
43b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    SCO,
44b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    L2CAP,
45b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    TCP,
46b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly};
47b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
48b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct thread_args {
49b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int fd;
50b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int type;
513f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    int delay;
52b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly};
53b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
54b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_un  local_addr_un  = {AF_UNIX, "/data/foo"};
553f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystruct sockaddr_rc  local_addr_rc  = {AF_BLUETOOTH, *BDADDR_ANY, 4};
563f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystruct sockaddr_sco local_addr_sco = {AF_BLUETOOTH, *BDADDR_LOCAL};
57b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_l2  local_addr_l2  = {AF_BLUETOOTH, htobs(0x1001), *BDADDR_ANY, 0};
58b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_in  local_addr_in  = {AF_INET, 9999, {0}, {0}};
59b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
60b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_un  remote_addr_un  ;
61b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_rc  remote_addr_rc  ;
62b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_sco remote_addr_sco ;
63b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_l2  remote_addr_l2  ;
64b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_in  remote_addr_in  ;
65b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
66b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _socket(int type) {
67b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int ret;
68b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int family = -1;
69b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int typ = -1;
70b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int protocol = -1;
71b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
72b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    switch (type) {
73b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case UNIX:
74b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        family = PF_UNIX;
75b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        typ = SOCK_STREAM;
76b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        protocol = 0;
77b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
78b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case RFCOMM:
79b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        family = PF_BLUETOOTH;
80b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        typ = SOCK_STREAM;
81b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        protocol = BTPROTO_RFCOMM;
82b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
83b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case SCO:
84b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        family = PF_BLUETOOTH;
85b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        typ = SOCK_SEQPACKET;
86b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        protocol = BTPROTO_SCO;
87b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
88b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case L2CAP:
89b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        family = PF_BLUETOOTH;
90b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        typ = SOCK_SEQPACKET;
91b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        protocol = BTPROTO_L2CAP;
92b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
93b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case TCP:
94b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        family = PF_INET;
95b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        typ = SOCK_STREAM;
96b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        protocol = 0;
97b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
98b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
99b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
100b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: socket()\n", gettid());
101b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    ret = socket(family, typ, protocol);
102b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: socket() = %d\n", gettid(), ret);
103b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
104b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
105b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return ret;
106b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
107b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
108b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _close(int fd, int type) {
109b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int ret;
110b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
111b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: close(%d)\n", gettid(), fd);
112b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    ret = close(fd);
113b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: close(%d) = %d\n", gettid(), fd, ret);
114b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
115b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
116b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return ret;
117b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
118b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
119b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _bind(int fd, int type) {
120b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int len = 0;
121b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int ret;
122b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    struct sockaddr *addr = NULL;
123b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
124b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    switch (type) {
125b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case UNIX:
126b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        unlink(local_addr_un.sun_path);
127b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_un;
128b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_un);
129b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
130b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case RFCOMM:
131b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_rc;
132b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_rc);
133b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
134b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case SCO:
135b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_sco;
136b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_sco);
137b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
138b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case L2CAP:
139b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_l2;
140b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_l2);
141b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
142b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case TCP:
143b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_in;
144b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_in);
145b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
146b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
147b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
148b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: bind(%d)\n", gettid(), fd);
149b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    ret = bind(fd, addr, len);
150b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: bind(%d) = %d\n", gettid(), fd, ret);
151b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
152b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
153b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return ret;
154b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
155b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
156b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _listen(int fd, int type) {
157b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int ret;
158b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
159b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: listen(%d)\n", gettid(), fd);
160b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    ret = listen(fd, 1);
161b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: listen(%d) = %d\n", gettid(), fd, ret);
162b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
163b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
164b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return ret;
165b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
166b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
167b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _accept(int fd, int type) {
168b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int ret;
169b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int len;
170b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    struct sockaddr *addr = NULL;
171b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
172b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    switch (type) {
173b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case UNIX:
174b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &remote_addr_un;
175b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(remote_addr_un);
176b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
177b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case RFCOMM:
178b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &remote_addr_rc;
179b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(remote_addr_rc);
180b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
181b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case SCO:
182b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &remote_addr_sco;
183b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(remote_addr_sco);
184b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
185b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case L2CAP:
186b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &remote_addr_l2;
187b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(remote_addr_l2);
188b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
189b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case TCP:
190b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &remote_addr_in;
191b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(remote_addr_in);
192b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
193b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
194b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
195b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: accept(%d)\n", gettid(), fd);
196b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    ret = accept(fd, addr, &len);
197b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: accept(%d) = %d\n", gettid(), fd, ret);
198b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
199b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    else {
200b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        printf("\tlen = %d\n", len);
201b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
202b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
203b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return ret;
204b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
205b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
206b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _connect(int fd, int type) {
207b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int ret;
2083f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    int len = 0;
209b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    struct sockaddr *addr = NULL;
210b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
211b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    switch (type) {
212b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case UNIX:
213b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_un;
214b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_un);
215b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
216b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case RFCOMM:
217b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_rc;
218b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_rc);
219b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
220b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case SCO:
221b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_sco;
222b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_sco);
223b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
224b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case L2CAP:
225b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_l2;
226b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_l2);
227b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
228b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    case TCP:
229b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        addr = (struct sockaddr *) &local_addr_in;
230b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        len = sizeof(local_addr_in);
231b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        break;
232b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
233b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
234b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: connect(%d)\n", gettid(), fd);
235b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    ret = connect(fd, addr, len);
236b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: connect(%d) = %d\n", gettid(), fd, ret);
237b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
238b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
239b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return ret;
240b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
241b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
242b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _write(int fd, int type) {
243b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int ret;
244b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    char buf = 0;
245b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
246b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: write(%d)\n", gettid(), fd);
247b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    ret = write(fd, &buf, 1);
248b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: connect(%d) = %d\n", gettid(), fd, ret);
249b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
250b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
251b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return ret;
252b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
253b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
2543f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic void thread_delay_close(struct thread_args *args) {
255b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: START\n", gettid());
2563f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    sleep(args->delay);
2573f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    _close(args->fd, args->type);
258b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: END\n", gettid());
259b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
260b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
2613f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic void thread_delay_close_write(struct thread_args *args) {
2623f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    printf("%d: START\n", gettid());
2633f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    sleep(args->delay);
2643f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    _close(args->fd, args->type);
2653f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    sleep(args->delay);
2663f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    _write(args->fd, args->type);
2673f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    printf("%d: END\n", gettid());
2683f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly}
269b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
2703f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic void thread_delay_connect(struct thread_args *args) {
271b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: START\n", gettid());
2723f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    sleep(args->delay);
2733f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    args->fd = _socket(args->type);
2743f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    _connect(args->fd, args->type);
275b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("%d: END\n", gettid());
276b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
277b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
2783f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic int do_accept_accept_accept(int type) {
2793f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    int fd;
2803f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
2813f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    fd = _socket(type);
2823f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    if (fd < 0) goto error;
2833f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
2843f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    if (_bind(fd, type) < 0) goto error;
2853f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
2863f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    if (_listen(fd, type) < 0) goto error;
2873f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
2883f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    while (1) {
2893f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly        _accept(fd, type);
2903f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    }
2913f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
2923f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    return 0;
2933f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
2943f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellyerror:
2953f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    return -1;
2963f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly}
2973f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
298b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int do_accept_and_close(int type) {
299b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int fd;
300b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    pthread_t thread;
3013f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    struct thread_args args = {-1, type, 1};
302b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
303b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    fd = _socket(type);
304b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (fd < 0) goto error;
305b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
306b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (_bind(fd, type) < 0) goto error;
307b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
308b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (_listen(fd, type) < 0) goto error;
309b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
3103f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    args.fd = fd;
3113f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_create(&thread, NULL, (void *)thread_delay_close, (void *)&args);
312b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
313b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    _accept(fd, type);
314b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
315b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    pthread_join(thread, NULL);
316b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
317b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return 0;
318b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
319b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellyerror:
320b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return -1;
321b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
322b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
323b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly// accept in one thread. close then write in another
324b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int do_accept_close_write(int type) {
325b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int fd;
326b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    pthread_t thread;
3273f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    struct thread_args args = {-1, type, 1};
328b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
329b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    fd = _socket(type);
330b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (fd < 0) goto error;
331b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
332b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (_bind(fd, type) < 0) goto error;
333b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
334b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (_listen(fd, type) < 0) goto error;
335b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
3363f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    args.fd = fd;
3373f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_create(&thread, NULL, (void *)thread_delay_close_write, (void *)&args);
338b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
339b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    _accept(fd, type);
340b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
341b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    pthread_join(thread, NULL);
342b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
343b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return 0;
344b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
345b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellyerror:
346b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return -1;
347b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
348b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
3493f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic int do_poll_poll_shutdown(int type) {
3503f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly#if 0
3513f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    int fd;
3523f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    struct thread_args a1 = {-1, type, 1};
3533f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    struct thread_args a2 = {-1, type, 2};
3543f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3553f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    fd = _socket(type);
3563f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3573f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_create(&t1, NULL, (void *)thread_poll, (void *)fd[0]);
3583f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_create(&t2, NULL, (void *)thread_poll, (void *)fd[0]);
3593f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3603f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    sleep(1);
3613f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3623f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    _shutdown(fd[1], SHUT_RDWR);
3633f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3643f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_join(t1, NULL);
3653f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_join(t2, NULL);
3663f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly#endif
3673f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    return 0;
3683f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly}
3693f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3703f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly// accept in one thread, connect from two different threads
3713f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic int do_accept_connect_connect(int type) {
3723f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    int fd;
3733f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_t t1;
3743f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_t t2;
3753f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    struct thread_args a1 = {-1, type, 1};
3763f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    struct thread_args a2 = {-1, type, 2};
3773f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3783f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    fd = _socket(type);
3793f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    if (fd < 0) goto error;
3803f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3813f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    if (_bind(fd, type) < 0) goto error;
3823f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3833f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    if (_listen(fd, type) < 0) goto error;
3843f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3853f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_create(&t1, NULL, (void *)thread_delay_connect, (void *)&a1);
3863f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_create(&t2, NULL, (void *)thread_delay_connect, (void *)&a2);
3873f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3883f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    _accept(fd, type);
3893f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3903f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_join(t1, NULL);
3913f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    pthread_join(t2, NULL);
3923f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3933f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    return 0;
3943f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
3953f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellyerror:
3963f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    return -1;
3973f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly}
3983f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly
399b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct {
400b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    char *name;
401b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int (*ptr)(int);
402b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} action_table[]  = {
4033f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    {"accept_accept_accept", do_accept_accept_accept},
404b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {"accept_and_close", do_accept_and_close},
405b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {"accept_close_write", do_accept_close_write},
4063f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly    {"accept_connect_connect", do_accept_connect_connect},
407b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {NULL, NULL},
408b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly};
409b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
410b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct {
411b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    char *name;
412b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    enum sock_type type;
413b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} type_table[]  = {
414b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {"unix", UNIX},
415b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {"rfcomm", RFCOMM},
416b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {"sco", SCO},
417b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {"l2cap", L2CAP},
418b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {"tcp", TCP},
419b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    {NULL, -1},
420b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly};
421b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
422b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic void usage() {
423b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int i;
424b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
425b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("socktest TYPE ACTION\n");
426b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("\nTYPE:\n");
427b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    for (i = 0; type_table[i].name; i++) {
428b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        printf("\t%s\n", type_table[i].name);
429b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
430b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    printf("\nACTION:\n");
431b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    for (i = 0; action_table[i].name; i++) {
432b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        printf("\t%s\n", action_table[i].name);
433b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
434b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
435b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
436b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellyint main(int argc, char **argv) {
437b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int i;
438b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    int type = -1;
439b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly
440b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (argc != 3) {
441b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        usage();
442b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        return -1;
443b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
444b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    for (i = 0; type_table[i].name; i++) {
445b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        if (!strcmp(argv[1], type_table[i].name)) {
446b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly            type = type_table[i].type;
447b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly            break;
448b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        }
449b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
450b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    if (type == -1) {
451b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        usage();
452b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        return -1;
453b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
454b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    for (i = 0; action_table[i].name; i++) {
455b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        if (!strcmp(argv[2], action_table[i].name)) {
456b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly            printf("TYPE = %s ACTION = %s\n", type_table[type].name,
457b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly                    action_table[i].name);
458b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly            return (*action_table[i].ptr)(type);
459b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly        }
460b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    }
461b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    usage();
462b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly    return -1;
463b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}
464