8 #include <sys/socket.h>
11 #include "constants.h"
14 #include "params.h" // verbose, do_specific_proto
15 #include "protocols.h"
21 unsigned int nr_sockets
= 0;
23 static const char *cachefilename
="trinity.socketcache";
25 #define MAX_PER_DOMAIN 5
26 #define MAX_TRIES_PER_DOMAIN 10
28 static int open_socket(unsigned int domain
, unsigned int type
, unsigned int protocol
)
32 struct sockaddr
*sa
= NULL
;
34 struct sockopt so
= { 0, 0, 0, 0 };
36 fd
= socket(domain
, type
, protocol
);
40 shm
->sockets
[nr_sockets
].fd
= fd
;
41 shm
->sockets
[nr_sockets
].triplet
.family
= domain
;
42 shm
->sockets
[nr_sockets
].triplet
.type
= type
;
43 shm
->sockets
[nr_sockets
].triplet
.protocol
= protocol
;
45 output(2, "fd[%i] = domain:%i (%s) type:0x%x protocol:%i\n",
46 fd
, domain
, get_proto_name(domain
), type
, protocol
);
50 /* Set some random socket options. */
51 sso_socket(&shm
->sockets
[nr_sockets
].triplet
, &so
, fd
);
53 /* Sometimes, listen on created sockets. */
55 /* fake a sockaddr. */
56 generate_sockaddr((unsigned long **) &sa
, (unsigned long *) &salen
, domain
);
58 ret
= bind(fd
, sa
, salen
);
60 debugf("bind: %s\n", strerror(errno));
62 debugf("bind: success!\n");
64 ret
= listen(fd
, (rand() % 2) + 1);
66 debugf("listen: %s\n", strerror(errno));
68 debugf("listen: success!\n");
77 static void lock_cachefile(int cachefile
, int type
)
89 output(2, "waiting on lock for cachefile\n");
91 if (fcntl(cachefile
, F_SETLKW
, &fl
) == -1) {
92 perror("fcntl F_SETLKW");
97 output(2, "took lock for cachefile\n");
100 static void unlock_cachefile(int cachefile
)
105 .l_whence
= SEEK_SET
,
111 if (fcntl(cachefile
, F_SETLK
, &fl
) == -1) {
112 perror("fcntl F_UNLCK F_SETLK ");
117 output(2, "dropped lock for cachefile\n");
120 static void generate_sockets(void)
124 unsigned int nr_to_create
= NR_SOCKET_FDS
;
125 unsigned int buffer
[3];
127 cachefile
= creat(cachefilename
, S_IWUSR
|S_IRUSR
);
129 outputerr("Couldn't open cachefile for writing! (%s)\n",
134 lock_cachefile(cachefile
, F_WRLCK
);
137 * Don't loop forever if all protos all are disabled.
139 if (!do_specific_proto
) {
140 for (n
= 0; n
< (int)ARRAY_SIZE(no_protos
); n
++) {
145 if (n
>= (int)ARRAY_SIZE(no_protos
))
149 while (nr_to_create
> 0) {
151 struct socket_triplet st
;
153 if (shm
->exit_reason
!= STILL_RUNNING
) {
158 for (st
.family
= 0; st
.family
< TRINITY_PF_MAX
; st
.family
++) {
160 if (do_specific_proto
== TRUE
)
161 st
.family
= specific_proto
;
163 if (get_proto_name(st
.family
) == NULL
)
166 BUG_ON(st
.family
>= ARRAY_SIZE(no_protos
));
167 if (no_protos
[st
.family
])
170 if (sanitise_socket_triplet(&st
) == -1)
171 rand_proto_type(&st
);
173 fd
= open_socket(st
.family
, st
.type
, st
.protocol
);
177 buffer
[0] = st
.family
;
179 buffer
[2] = st
.protocol
;
180 n
= write(cachefile
, &buffer
, sizeof(int) * 3);
182 outputerr("something went wrong writing the cachefile!\n");
186 if (nr_to_create
== 0)
189 //outputerr("Couldn't open family:%d (%s)\n", st.family, get_proto_name(st.family));
193 /* check for ctrl-c */
194 if (shm
->exit_reason
!= STILL_RUNNING
)
197 //FIXME: If we've passed -P and we're spinning here without making progress
198 // then we should abort after a few hundred loops.
203 unlock_cachefile(cachefile
);
205 output(1, "created %d sockets\n", nr_sockets
);
211 void close_sockets(void)
216 struct linger ling
= { .l_onoff
= FALSE
, };
218 for (i
= 0; i
< nr_sockets
; i
++) {
220 //FIXME: This is a workaround for a weird bug where we hang forevre
221 // waiting for bluetooth sockets when we setsockopt.
222 // Hopefully at some point we can remove this when someone figures out what's going on.
223 if (shm
->sockets
[i
].triplet
.family
== PF_BLUETOOTH
)
226 /* Grab an fd, and nuke it before someone else uses it. */
227 fd
= shm
->sockets
[i
].fd
;
228 shm
->sockets
[i
].fd
= 0;
231 r
= setsockopt(fd
, SOL_SOCKET
, SO_LINGER
, &ling
, sizeof(struct linger
));
233 perror("setsockopt");
235 r
= shutdown(fd
, SHUT_RDWR
);
240 output(1, "failed to close socket [%d:%d:%d].(%s)\n",
241 shm
->sockets
[i
].triplet
.family
,
242 shm
->sockets
[i
].triplet
.type
,
243 shm
->sockets
[i
].triplet
.protocol
,
250 void open_sockets(void)
253 unsigned int domain
, type
, protocol
;
254 unsigned int buffer
[3];
258 cachefile
= open(cachefilename
, O_RDONLY
);
260 output(1, "Couldn't find socket cachefile. Regenerating.\n");
265 lock_cachefile(cachefile
, F_RDLCK
);
267 while (bytesread
!= 0) {
268 bytesread
= read(cachefile
, buffer
, sizeof(int) * 3);
274 protocol
= buffer
[2];
276 if ((do_specific_proto
== TRUE
&& domain
!= specific_proto
) ||
277 (domain
< ARRAY_SIZE(no_protos
) && no_protos
[domain
] == TRUE
)) {
278 output(1, "ignoring socket cachefile due to specific "
279 "protocol request (or protocol disabled), "
280 "and stale data in cachefile.\n");
282 unlock_cachefile(cachefile
); /* drop the reader lock. */
284 unlink(cachefilename
);
289 fd
= open_socket(domain
, type
, protocol
);
291 output(1, "Cachefile is stale. Need to regenerate.\n");
296 /* check for ctrl-c */
297 if (shm
->exit_reason
!= STILL_RUNNING
) {
303 if (nr_sockets
< NR_SOCKET_FDS
) {
304 output(1, "Insufficient sockets in cachefile (%d). Regenerating.\n", nr_sockets
);
308 output(1, "%d sockets created based on info from socket cachefile.\n", nr_sockets
);
310 unlock_cachefile(cachefile
);