Line data Source code
1 : #include "../../../burp.h"
2 : #include "../../../asfd.h"
3 : #include "../../../async.h"
4 : #include "../../../cmd.h"
5 : #include "../../../conf.h"
6 : #include "../../../fsops.h"
7 : #include "../../../lock.h"
8 : #include "../../../log.h"
9 : #include "../../../prepend.h"
10 : #include "champ_client.h"
11 : #include "champ_chooser.h"
12 : #include "champ_server.h"
13 :
14 : #include <sys/un.h>
15 :
16 0 : static int champ_chooser_fork(struct sdirs *sdirs, struct conf **confs)
17 : {
18 0 : pid_t childpid=-1;
19 :
20 0 : if(!get_int(confs[OPT_FORK]))
21 : {
22 0 : logp("Not forking a champ chooser process.\n");
23 : // They need to manually run a separate process.
24 0 : return 0;
25 : }
26 :
27 0 : switch((childpid=fork()))
28 : {
29 : case -1:
30 : logp("fork failed in %s: %s\n",
31 0 : __func__, strerror(errno));
32 0 : return -1;
33 : case 0:
34 : // Child.
35 : int cret;
36 0 : log_fzp_set(NULL, confs);
37 0 : switch(champ_chooser_server(sdirs, confs))
38 : {
39 0 : case 0: cret=0;
40 0 : default: cret=1;
41 : }
42 0 : exit(cret);
43 : default:
44 : // Parent.
45 0 : logp("forked champ chooser pid %d\n", childpid);
46 0 : return 0;
47 : }
48 : return -1; // Not reached.
49 : }
50 :
51 0 : static int connect_to_champ_chooser(struct sdirs *sdirs, struct conf **confs)
52 : {
53 : int len;
54 0 : int s=-1;
55 0 : int tries=0;
56 0 : int tries_max=3;
57 : struct sockaddr_un remote;
58 :
59 0 : if(!lock_test(sdirs->champlock))
60 : {
61 : // Champ chooser is not running.
62 : // Try to fork a new champ chooser process.
63 0 : if(champ_chooser_fork(sdirs, confs)) return -1;
64 : }
65 :
66 : // Champ chooser should either be running now, or about to run.
67 :
68 0 : if((s=socket(AF_UNIX, SOCK_STREAM, 0))<0)
69 : {
70 0 : logp("socket error in %s: %s\n", __func__, strerror(errno));
71 0 : return -1;
72 : }
73 :
74 0 : memset(&remote, 0, sizeof(struct sockaddr_un));
75 0 : remote.sun_family=AF_UNIX;
76 0 : strcpy(remote.sun_path, sdirs->champsock);
77 0 : len=strlen(remote.sun_path)+sizeof(remote.sun_family);
78 :
79 0 : while(tries++<tries_max)
80 : {
81 0 : int sleeptimeleft=3;
82 0 : if(!connect(s, (struct sockaddr *)&remote, len))
83 : {
84 0 : logp("Connected to champ chooser.\n");
85 0 : return s;
86 : }
87 :
88 : // SIGCHLDs may be interrupting.
89 0 : sleeptimeleft=3;
90 0 : while(sleeptimeleft>0) sleeptimeleft=sleep(sleeptimeleft);
91 : }
92 :
93 : // Only log any error after all attempts failed, to make the logs
94 : // less worrying (most of the time, the first attempt will fail).
95 : logp("Could not connect to champ chooser on %s after %d attempts: %s\n",
96 0 : sdirs->champsock, tries_max, strerror(errno));
97 :
98 0 : return -1;
99 : }
100 :
101 0 : struct asfd *champ_chooser_connect(struct async *as,
102 : struct sdirs *sdirs, struct conf **confs)
103 : {
104 0 : int champsock=-1;
105 0 : char *champname=NULL;
106 0 : struct asfd *chfd=NULL;
107 0 : const char *cname=NULL;
108 :
109 : // Connect to champ chooser now.
110 : // This may start up a new champ chooser. On a machine with multiple
111 : // cores, it may be faster to do now, way before it is actually needed
112 : // in phase2.
113 0 : if((champsock=connect_to_champ_chooser(sdirs, confs))<0)
114 : {
115 0 : logp("could not connect to champ chooser\n");
116 0 : goto error;
117 : }
118 :
119 0 : if(!(chfd=setup_asfd(as, "champ chooser socket", &champsock, NULL,
120 : ASFD_STREAM_STANDARD, ASFD_FD_SERVER_TO_CHAMP_CHOOSER, -1,
121 0 : confs))) goto error;
122 :
123 0 : cname=get_string(confs[OPT_CNAME]);
124 0 : if(!(champname=prepend_n("cname", cname, strlen(cname), ":")))
125 0 : goto error;
126 :
127 0 : if(chfd->write_str(chfd, CMD_GEN, champname)
128 0 : || chfd->read_expect(chfd, CMD_GEN, "cname ok"))
129 0 : goto error;
130 :
131 0 : free(champname);
132 0 : return chfd;
133 : error:
134 0 : free(champname);
135 0 : as->asfd_remove(as, chfd);
136 0 : asfd_free(&chfd);
137 0 : close_fd(&champsock);
138 0 : return NULL;
139 : }
|