8 #include <sys/socket.h>
11 #include "constants.h"
15 #include "params.h" // verbose, do_specific_proto
16 #include "protocols.h"
22 unsigned int nr_sockets
= 0;
24 static const char *cachefilename
="trinity.socketcache";
26 #define MAX_PER_DOMAIN 5
27 #define MAX_TRIES_PER_DOMAIN 10
29 static int open_socket(unsigned int domain
, unsigned int type
, unsigned int protocol
)
33 struct sockaddr
*sa
= NULL
;
35 struct sockopt so
= { 0, 0, 0, 0 };
37 fd
= socket(domain
, type
, protocol
);
41 shm
->sockets
[nr_sockets
].fd
= fd
;
42 shm
->sockets
[nr_sockets
].triplet
.family
= domain
;
43 shm
->sockets
[nr_sockets
].triplet
.type
= type
;
44 shm
->sockets
[nr_sockets
].triplet
.protocol
= protocol
;
46 output(2, "fd[%i] = domain:%i (%s) type:0x%x protocol:%i\n",
47 fd
, domain
, get_proto_name(domain
), type
, protocol
);
49 /* Set some random socket options. */
50 sso_socket(&shm
->sockets
[nr_sockets
].triplet
, &so
, fd
);
54 /* Sometimes, listen on created sockets. */
56 /* fake a sockaddr. */
57 generate_sockaddr((struct sockaddr
**) &sa
, (socklen_t
*) &salen
, domain
);
59 ret
= bind(fd
, sa
, salen
);
61 debugf("bind: %s\n", strerror(errno));
63 debugf("bind: success!\n");
65 ret
= listen(fd
, (rand() % 2) + 1);
67 debugf("listen: %s\n", strerror(errno));
69 debugf("listen: success!\n");
73 /* If we didn't have a function for this sockaddr type, we would
74 * have returned page_rand, so don't free() it or we segv. */
75 if (sa
== (struct sockaddr
*) page_rand
)
84 static void lock_cachefile(int cachefile
, int type
)
96 output(2, "waiting on lock for cachefile\n");
98 if (fcntl(cachefile
, F_SETLKW
, &fl
) == -1) {
99 perror("fcntl F_SETLKW");
104 output(2, "took lock for cachefile\n");
107 static void unlock_cachefile(int cachefile
)
112 .l_whence
= SEEK_SET
,
118 if (fcntl(cachefile
, F_SETLK
, &fl
) == -1) {
119 perror("fcntl F_UNLCK F_SETLK ");
124 output(2, "dropped lock for cachefile\n");
127 static void generate_sockets(void)
131 unsigned int nr_to_create
= NR_SOCKET_FDS
;
132 unsigned int buffer
[3];
134 cachefile
= creat(cachefilename
, S_IWUSR
|S_IRUSR
);
136 outputerr("Couldn't open cachefile for writing! (%s)\n",
141 lock_cachefile(cachefile
, F_WRLCK
);
144 * Don't loop forever if all protos all are disabled.
146 if (!do_specific_proto
) {
147 for (n
= 0; n
< (int)ARRAY_SIZE(no_protos
); n
++) {
152 if (n
>= (int)ARRAY_SIZE(no_protos
))
156 while (nr_to_create
> 0) {
158 struct socket_triplet st
;
160 if (shm
->exit_reason
!= STILL_RUNNING
) {
165 for (st
.family
= 0; st
.family
< TRINITY_PF_MAX
; st
.family
++) {
167 if (do_specific_proto
== TRUE
)
168 st
.family
= specific_proto
;
170 if (get_proto_name(st
.family
) == NULL
)
173 BUG_ON(st
.family
>= ARRAY_SIZE(no_protos
));
174 if (no_protos
[st
.family
])
177 if (sanitise_socket_triplet(&st
) == -1)
178 rand_proto_type(&st
);
180 fd
= open_socket(st
.family
, st
.type
, st
.protocol
);
184 buffer
[0] = st
.family
;
186 buffer
[2] = st
.protocol
;
187 n
= write(cachefile
, &buffer
, sizeof(int) * 3);
189 outputerr("something went wrong writing the cachefile!\n");
193 if (nr_to_create
== 0)
196 //outputerr("Couldn't open family:%d (%s)\n", st.family, get_proto_name(st.family));
200 /* check for ctrl-c */
201 if (shm
->exit_reason
!= STILL_RUNNING
)
204 //FIXME: If we've passed -P and we're spinning here without making progress
205 // then we should abort after a few hundred loops.
210 unlock_cachefile(cachefile
);
212 output(1, "created %d sockets\n", nr_sockets
);
218 void close_sockets(void)
223 struct linger ling
= { .l_onoff
= FALSE
, .l_linger
= 0 };
225 for (i
= 0; i
< nr_sockets
; i
++) {
227 //FIXME: This is a workaround for a weird bug where we hang forevre
228 // waiting for bluetooth sockets when we setsockopt.
229 // Hopefully at some point we can remove this when someone figures out what's going on.
230 if (shm
->sockets
[i
].triplet
.family
== PF_BLUETOOTH
)
233 /* Grab an fd, and nuke it before someone else uses it. */
234 fd
= shm
->sockets
[i
].fd
;
235 shm
->sockets
[i
].fd
= 0;
238 r
= setsockopt(fd
, SOL_SOCKET
, SO_LINGER
, &ling
, sizeof(struct linger
));
240 perror("setsockopt");
242 r
= shutdown(fd
, SHUT_RDWR
);
247 output(1, "failed to close socket [%d:%d:%d].(%s)\n",
248 shm
->sockets
[i
].triplet
.family
,
249 shm
->sockets
[i
].triplet
.type
,
250 shm
->sockets
[i
].triplet
.protocol
,
257 void open_sockets(void)
260 unsigned int domain
, type
, protocol
;
261 unsigned int buffer
[3];
265 cachefile
= open(cachefilename
, O_RDONLY
);
267 output(1, "Couldn't find socket cachefile. Regenerating.\n");
272 lock_cachefile(cachefile
, F_RDLCK
);
274 while (bytesread
!= 0) {
275 bytesread
= read(cachefile
, buffer
, sizeof(int) * 3);
281 protocol
= buffer
[2];
283 if ((do_specific_proto
== TRUE
&& domain
!= specific_proto
) ||
284 (domain
< ARRAY_SIZE(no_protos
) && no_protos
[domain
] == TRUE
)) {
285 output(1, "ignoring socket cachefile due to specific "
286 "protocol request (or protocol disabled), "
287 "and stale data in cachefile.\n");
289 unlock_cachefile(cachefile
); /* drop the reader lock. */
291 unlink(cachefilename
);
296 fd
= open_socket(domain
, type
, protocol
);
298 output(1, "Cachefile is stale. Need to regenerate.\n");
303 /* check for ctrl-c */
304 if (shm
->exit_reason
!= STILL_RUNNING
) {
310 if (nr_sockets
< NR_SOCKET_FDS
) {
311 output(1, "Insufficient sockets in cachefile (%d). Regenerating.\n", nr_sockets
);
315 output(1, "%d sockets created based on info from socket cachefile.\n", nr_sockets
);
317 unlock_cachefile(cachefile
);