8 #include <sys/socket.h>
12 #include "constants.h"
16 #include "params.h" // verbose, do_specific_proto
18 #include "protocols.h"
20 unsigned int nr_sockets
= 0;
22 static const char *cachefilename
="trinity.socketcache";
24 #define MAX_PER_DOMAIN 5
25 #define MAX_TRIES_PER_DOMAIN 10
27 static int open_socket(unsigned int domain
, unsigned int type
, unsigned int protocol
)
31 struct sockaddr
*sa
= NULL
;
33 struct sockopt so
= { 0, 0, 0, 0 };
35 fd
= socket(domain
, type
, protocol
);
39 shm
->sockets
[nr_sockets
].fd
= fd
;
40 shm
->sockets
[nr_sockets
].triplet
.family
= domain
;
41 shm
->sockets
[nr_sockets
].triplet
.type
= type
;
42 shm
->sockets
[nr_sockets
].triplet
.protocol
= protocol
;
44 output(2, "fd[%i] = domain:%i (%s) type:0x%x protocol:%i\n",
45 fd
, domain
, get_proto_name(domain
), type
, protocol
);
49 /* Set some random socket options. */
50 sso_socket(&shm
->sockets
[nr_sockets
].triplet
, &so
, fd
);
52 /* Sometimes, listen on created sockets. */
54 /* fake a sockaddr. */
55 generate_sockaddr((unsigned long **) &sa
, (unsigned long *) &salen
, domain
);
57 ret
= bind(fd
, sa
, salen
);
59 debugf("bind: %s\n", strerror(errno));
61 debugf("bind: success!\n");
63 ret
= listen(fd
, (rand() % 2) + 1);
65 debugf("listen: %s\n", strerror(errno));
67 debugf("listen: success!\n");
76 static void lock_cachefile(int cachefile
, int type
)
88 output(2, "waiting on lock for cachefile\n");
90 if (fcntl(cachefile
, F_SETLKW
, &fl
) == -1) {
91 perror("fcntl F_SETLKW");
96 output(2, "took lock for cachefile\n");
99 static void unlock_cachefile(int cachefile
)
104 .l_whence
= SEEK_SET
,
110 if (fcntl(cachefile
, F_SETLK
, &fl
) == -1) {
111 perror("fcntl F_UNLCK F_SETLK ");
116 output(2, "dropped lock for cachefile\n");
119 static void generate_sockets(void)
123 unsigned int nr_to_create
= NR_SOCKET_FDS
;
124 unsigned int buffer
[3];
126 cachefile
= creat(cachefilename
, S_IWUSR
|S_IRUSR
);
128 outputerr("Couldn't open cachefile for writing! (%s)\n",
133 lock_cachefile(cachefile
, F_WRLCK
);
136 * Don't loop forever if all protos all are disabled.
138 if (!do_specific_proto
) {
139 for (n
= 0; n
< (int)ARRAY_SIZE(no_protos
); n
++) {
144 if (n
>= (int)ARRAY_SIZE(no_protos
))
148 while (nr_to_create
> 0) {
150 struct socket_triplet st
;
152 if (shm
->exit_reason
!= STILL_RUNNING
) {
157 for (st
.family
= 0; st
.family
< TRINITY_PF_MAX
; st
.family
++) {
159 if (do_specific_proto
== TRUE
)
160 st
.family
= specific_proto
;
162 if (get_proto_name(st
.family
) == NULL
)
165 BUG_ON(st
.family
>= ARRAY_SIZE(no_protos
));
166 if (no_protos
[st
.family
])
169 if (sanitise_socket_triplet(&st
) == -1)
170 rand_proto_type(&st
);
172 fd
= open_socket(st
.family
, st
.type
, st
.protocol
);
176 buffer
[0] = st
.family
;
178 buffer
[2] = st
.protocol
;
179 n
= write(cachefile
, &buffer
, sizeof(int) * 3);
181 outputerr("something went wrong writing the cachefile!\n");
185 if (nr_to_create
== 0)
188 //outputerr("Couldn't open family:%d (%s)\n", st.family, get_proto_name(st.family));
192 /* check for ctrl-c */
193 if (shm
->exit_reason
!= STILL_RUNNING
)
196 //FIXME: If we've passed -P and we're spinning here without making progress
197 // then we should abort after a few hundred loops.
202 unlock_cachefile(cachefile
);
204 output(1, "created %d sockets\n", nr_sockets
);
210 void close_sockets(void)
215 struct linger ling
= { .l_onoff
= FALSE
, };
217 for (i
= 0; i
< nr_sockets
; i
++) {
219 //FIXME: This is a workaround for a weird bug where we hang forevre
220 // waiting for bluetooth sockets when we setsockopt.
221 // Hopefully at some point we can remove this when someone figures out what's going on.
222 if (shm
->sockets
[i
].triplet
.family
== PF_BLUETOOTH
)
225 /* Grab an fd, and nuke it before someone else uses it. */
226 fd
= shm
->sockets
[i
].fd
;
227 shm
->sockets
[i
].fd
= 0;
230 r
= setsockopt(fd
, SOL_SOCKET
, SO_LINGER
, &ling
, sizeof(struct linger
));
232 perror("setsockopt");
234 r
= shutdown(fd
, SHUT_RDWR
);
239 output(1, "failed to close socket [%d:%d:%d].(%s)\n",
240 shm
->sockets
[i
].triplet
.family
,
241 shm
->sockets
[i
].triplet
.type
,
242 shm
->sockets
[i
].triplet
.protocol
,
249 void open_sockets(void)
252 unsigned int domain
, type
, protocol
;
253 unsigned int buffer
[3];
257 cachefile
= open(cachefilename
, O_RDONLY
);
259 output(1, "Couldn't find socket cachefile. Regenerating.\n");
264 lock_cachefile(cachefile
, F_RDLCK
);
266 while (bytesread
!= 0) {
267 bytesread
= read(cachefile
, buffer
, sizeof(int) * 3);
273 protocol
= buffer
[2];
275 if ((do_specific_proto
== TRUE
&& domain
!= specific_proto
) ||
276 (domain
< ARRAY_SIZE(no_protos
) && no_protos
[domain
] == TRUE
)) {
277 output(1, "ignoring socket cachefile due to specific "
278 "protocol request (or protocol disabled), "
279 "and stale data in cachefile.\n");
281 unlock_cachefile(cachefile
); /* drop the reader lock. */
283 unlink(cachefilename
);
288 fd
= open_socket(domain
, type
, protocol
);
290 output(1, "Cachefile is stale. Need to regenerate.\n");
295 /* check for ctrl-c */
296 if (shm
->exit_reason
!= STILL_RUNNING
) {
302 if (nr_sockets
< NR_SOCKET_FDS
) {
303 output(1, "Insufficient sockets in cachefile (%d). Regenerating.\n", nr_sockets
);
307 output(1, "%d sockets created based on info from socket cachefile.\n", nr_sockets
);
309 unlock_cachefile(cachefile
);