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