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
)
32 struct sockopt so
= { 0, 0, 0, 0 };
34 fd
= socket(domain
, type
, protocol
);
38 shm
->sockets
[nr_sockets
].fd
= fd
;
39 shm
->sockets
[nr_sockets
].triplet
.family
= domain
;
40 shm
->sockets
[nr_sockets
].triplet
.type
= type
;
41 shm
->sockets
[nr_sockets
].triplet
.protocol
= protocol
;
43 output(2, "fd[%i] = domain:%i (%s) type:0x%x protocol:%i\n",
44 fd
, domain
, get_proto_name(domain
), type
, protocol
);
48 /* skip over bluetooth due to weird linger bug */
49 if (domain
== PF_BLUETOOTH
)
52 /* Set some random socket options. */
55 ret
= setsockopt(fd
, so
.level
, so
.optname
, (void *)so
.optval
, so
.optlen
);
57 output(1, "Setsockopt(%lx %lx %lx %lx) on fd %d\n",
58 so
.level
, so
.optname
, so
.optval
, so
.optlen
, fd
);
64 /* Sometimes, listen on created sockets. */
66 /* fake a sockaddr. */
67 generate_sockaddr((unsigned long *) &sa
, (unsigned long *) &salen
, domain
);
69 ret
= bind(fd
, &sa
, salen
);
71 debugf("bind: %s\n", strerror(errno));
73 debugf("bind: success!\n");
75 ret
= listen(fd
, (rand() % 2) + 1);
77 debugf("listen: %s\n", strerror(errno));
79 debugf("listen: success!\n");
86 static void lock_cachefile(int cachefile
, int type
)
98 output(2, "waiting on lock for cachefile\n");
100 if (fcntl(cachefile
, F_SETLKW
, &fl
) == -1) {
101 perror("fcntl F_SETLKW");
106 output(2, "took lock for cachefile\n");
109 static void unlock_cachefile(int cachefile
)
114 .l_whence
= SEEK_SET
,
120 if (fcntl(cachefile
, F_SETLK
, &fl
) == -1) {
121 perror("fcntl F_UNLCK F_SETLK ");
126 output(2, "dropped lock for cachefile\n");
129 static void generate_sockets(void)
133 unsigned int nr_to_create
= NR_SOCKET_FDS
;
134 unsigned int buffer
[3];
136 cachefile
= creat(cachefilename
, S_IWUSR
|S_IRUSR
);
138 outputerr("Couldn't open cachefile for writing! (%s)\n",
143 lock_cachefile(cachefile
, F_WRLCK
);
146 * Don't loop forever if all protos all are disabled.
148 if (!do_specific_proto
) {
149 for (n
= 0; n
< (int)ARRAY_SIZE(no_protos
); n
++) {
154 if (n
>= (int)ARRAY_SIZE(no_protos
))
158 while (nr_to_create
> 0) {
160 struct socket_triplet st
;
162 if (shm
->exit_reason
!= STILL_RUNNING
) {
167 for (st
.family
= 0; st
.family
< TRINITY_PF_MAX
; st
.family
++) {
169 if (do_specific_proto
== TRUE
)
170 st
.family
= specific_proto
;
172 if (get_proto_name(st
.family
) == NULL
)
175 BUG_ON(st
.family
>= ARRAY_SIZE(no_protos
));
176 if (no_protos
[st
.family
])
179 if (sanitise_socket_triplet(&st
) == -1)
180 rand_proto_type(&st
);
182 fd
= open_socket(st
.family
, st
.type
, st
.protocol
);
186 buffer
[0] = st
.family
;
188 buffer
[2] = st
.protocol
;
189 n
= write(cachefile
, &buffer
, sizeof(int) * 3);
191 outputerr("something went wrong writing the cachefile!\n");
195 if (nr_to_create
== 0)
198 //outputerr("Couldn't open family:%d (%s)\n", st.family, get_proto_name(st.family));
202 /* check for ctrl-c */
203 if (shm
->exit_reason
!= STILL_RUNNING
)
206 //FIXME: If we've passed -P and we're spinning here without making progress
207 // then we should abort after a few hundred loops.
212 unlock_cachefile(cachefile
);
214 output(1, "created %d sockets\n", nr_sockets
);
220 void close_sockets(void)
225 struct linger ling
= { .l_onoff
= FALSE
, };
227 for (i
= 0; i
< nr_sockets
; i
++) {
229 //FIXME: This is a workaround for a weird bug where we hang forevre
230 // waiting for bluetooth sockets when we setsockopt.
231 // Hopefully at some point we can remove this when someone figures out what's going on.
232 if (shm
->sockets
[i
].triplet
.family
== PF_BLUETOOTH
)
235 /* Grab an fd, and nuke it before someone else uses it. */
236 fd
= shm
->sockets
[i
].fd
;
237 shm
->sockets
[i
].fd
= 0;
240 r
= setsockopt(fd
, SOL_SOCKET
, SO_LINGER
, &ling
, sizeof(struct linger
));
242 perror("setsockopt");
244 r
= shutdown(fd
, SHUT_RDWR
);
249 output(1, "failed to close socket [%d:%d:%d].(%s)\n",
250 shm
->sockets
[i
].triplet
.family
,
251 shm
->sockets
[i
].triplet
.type
,
252 shm
->sockets
[i
].triplet
.protocol
,
259 void open_sockets(void)
262 unsigned int domain
, type
, protocol
;
263 unsigned int buffer
[3];
267 cachefile
= open(cachefilename
, O_RDONLY
);
269 output(1, "Couldn't find socket cachefile. Regenerating.\n");
274 lock_cachefile(cachefile
, F_RDLCK
);
276 while (bytesread
!= 0) {
277 bytesread
= read(cachefile
, buffer
, sizeof(int) * 3);
283 protocol
= buffer
[2];
285 if ((do_specific_proto
== TRUE
&& domain
!= specific_proto
) ||
286 (domain
< ARRAY_SIZE(no_protos
) && no_protos
[domain
] == TRUE
)) {
287 output(1, "ignoring socket cachefile due to specific "
288 "protocol request (or protocol disabled), "
289 "and stale data in cachefile.\n");
291 unlock_cachefile(cachefile
); /* drop the reader lock. */
293 unlink(cachefilename
);
298 fd
= open_socket(domain
, type
, protocol
);
300 output(1, "Cachefile is stale. Need to regenerate.\n");
305 /* check for ctrl-c */
306 if (shm
->exit_reason
!= STILL_RUNNING
) {
312 if (nr_sockets
< NR_SOCKET_FDS
) {
313 output(1, "Insufficient sockets in cachefile (%d). Regenerating.\n", nr_sockets
);
317 output(1, "%d sockets created based on info from socket cachefile.\n", nr_sockets
);
319 unlock_cachefile(cachefile
);