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