]> andersk Git - moira.git/blame - lib/mr_connect.c
update for dirremote->dirmailhide
[moira.git] / lib / mr_connect.c
CommitLineData
fa59b86f 1/* $Id$
e2a67c78 2 *
7ac48069 3 * This routine is part of the client library. It handles
4 * creating a connection to the moira server.
5eaef520 5 *
7ac48069 6 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
e2a67c78 9 */
10
babbc197 11#include <mit-copyright.h>
7ac48069 12#include <moira.h>
8defc06b 13#include <moira_site.h>
7ac48069 14#include "mr_private.h"
15
85330553 16#include <sys/types.h>
17#include <sys/socket.h>
18
19#include <netinet/in.h>
20#include <netdb.h>
21
7ac48069 22#include <errno.h>
a43ce477 23#include <stdlib.h>
7ac48069 24#include <string.h>
85330553 25#include <unistd.h>
7ac48069 26
a43ce477 27#include <hesiod.h>
05fb8281 28
7ac48069 29RCSID("$Header$");
30
85330553 31int _mr_conn = 0;
32static char *mr_server_host = NULL;
33
34/* mrgdb compatibility magic
35
36 The data looks like this:
37
38 client -> server
39 00000036 [length of rest of packet]
40 00000004 [number of fields]
41 01 01 01 01 [types of fields: 4 strings]
42 "server_id\0parms\0host\0user\0" [field names]
43 00000001 [length of null-terminated server_id]
44 "\0" [server_id: ignored anyway]
45 00000001 [length of null-terminated parms]
46 "\0" [parms: ignored anyway]
47 00000001 [length of null-terminated client host]
48 "\0" [host: ignored anyway]
49 00000001 [length of null-terminated client name]
50 "\0" [user: ignored anyway]
51
52 server -> client
53 00000031 [length of rest of packet]
54 00000003 [number of fields]
55 00 01 01 [types of fields: int and 2 strings]
56 "disposition\0server_id\0parms\0" [field names]
57 00000001 [GDB_ACCEPTED]
58 00000001 [length of null-terminated server_id]
59 "\0" [server_id: ignored anyway]
60 00000001 [length of null-terminated parms]
61 "\0" [parms: ignored anyway]
62
63*/
64
65static char challenge[58] = "\0\0\0\066\0\0\0\004\001\001\001\001server_id\0parms\0host\0user\0\0\0\0\001\0\0\0\0\001\0\0\0\0\001\0\0\0\0\001\0";
66static char response[53] = "\0\0\0\061\0\0\0\003\0\001\001disposition\0server_id\0parms\0\0\0\0\001\0\0\0\001\0\0\0\0\001\0";
e2a67c78 67
68/*
85330553 69 * Open a connection to the moira server. Looks for the server name
5450e3a1 70 * 1) passed as an argument, 2) in environment variable, 3) by hesiod
85330553 71 * 4) compiled in default
e2a67c78 72 */
73
5eaef520 74int mr_connect(char *server)
e2a67c78 75{
85330553 76 char *port, **pp, *sbuf = NULL;
77 struct hostent *shost;
5eaef520 78
5eaef520 79 if (_mr_conn)
80 return MR_ALREADY_CONNECTED;
85330553 81 if (!mr_inited)
82 mr_init();
5eaef520 83
84 if (!server || (strlen(server) == 0))
85 server = getenv("MOIRASERVER");
5450e3a1 86
87#ifdef HESIOD
5eaef520 88 if (!server || (strlen(server) == 0))
89 {
90 pp = hes_resolve("moira", "sloc");
91 if (pp)
92 server = *pp;
5450e3a1 93 }
a43ce477 94#endif
5450e3a1 95
5eaef520 96 if (!server || (strlen(server) == 0))
97 server = MOIRA_SERVER;
5450e3a1 98
85330553 99 shost = gethostbyname(server);
100 if (!shost)
101 return MR_CANT_CONNECT;
102
103 if (strchr(server, ':'))
5eaef520 104 {
85330553 105 int len = strcspn(server, ":");
106 sbuf = malloc(len + 1);
107 strncpy(sbuf, server, len);
108 sbuf[len - 1] = '\0';
5eaef520 109 server = sbuf;
85330553 110 port = strchr(server, ':') + 1;
111 }
112 else
113 port = strchr(MOIRA_SERVER, ':') + 1;
114
115 _mr_conn = mr_connect_internal(server, port);
116 free(sbuf);
117 if (!_mr_conn)
118 return MR_CANT_CONNECT;
119
120 /* stash hostname for later use */
121 mr_server_host = strdup(shost->h_name);
122 return MR_SUCCESS;
123}
124
125int mr_connect_internal(char *server, char *port)
126{
127 int fd, size, more;
128 struct sockaddr_in target;
129 struct hostent *shost;
130 char actualresponse[53];
131
132 shost = gethostbyname(server);
133 if (!shost)
134 return 0;
135
136 if (port[0] == '#')
137 target.sin_port = atoi(port + 1);
138 else
139 {
140 struct servent *s;
141 s = getservbyname(port, "tcp");
142 if (s)
143 target.sin_port = s->s_port;
144 else
145 return 0;
5450e3a1 146 }
147
85330553 148 memcpy(&target.sin_addr, shost->h_addr, shost->h_length);
149 target.sin_family = shost->h_addrtype;
150
151 fd = socket(AF_INET, SOCK_STREAM, 0);
152 if (fd < 0)
153 return 0;
154
155 if (connect(fd, (struct sockaddr *)&target, sizeof(target)) < 0)
5eaef520 156 {
85330553 157 close(fd);
158 return 0;
83e80378 159 }
05fb8281 160
85330553 161 /* Do magic mrgdb initialization */
162 size = write(fd, challenge, sizeof(challenge));
163 if (size != sizeof(challenge))
164 {
165 close(fd);
166 return 0;
167 }
168 for (size = 0; size < sizeof(actualresponse); size += more)
169 {
170 more = read(fd, actualresponse + size, sizeof(actualresponse) - size);
171 if (!more)
172 break;
173 }
174 if (size != sizeof(actualresponse))
175 {
176 close(fd);
177 return 0;
178 }
179 if (memcmp(actualresponse, response, sizeof(actualresponse)))
180 {
181 close(fd);
182 return 0;
183 }
05fb8281 184
85330553 185 /* You win */
186 return fd;
e2a67c78 187}
5eaef520 188
189int mr_disconnect(void)
e2a67c78 190{
5eaef520 191 CHECK_CONNECTED;
85330553 192 close(_mr_conn);
193 _mr_conn = 0;
5eaef520 194 free(mr_server_host);
85330553 195 mr_server_host = NULL;
196 return MR_SUCCESS;
e2a67c78 197}
198
5eaef520 199int mr_host(char *host, int size)
05fb8281 200{
5eaef520 201 CHECK_CONNECTED;
05fb8281 202
5eaef520 203 /* If we are connected, mr_server_host points to a valid string. */
204 strncpy(host, mr_server_host, size);
85330553 205 host[size - 1] = '\0';
206 return MR_SUCCESS;
05fb8281 207}
208
5eaef520 209int mr_noop(void)
e2a67c78 210{
5eaef520 211 int status;
85330553 212 mr_params params, reply;
5eaef520 213
214 CHECK_CONNECTED;
85330553 215 params.u.mr_procno = MR_NOOP;
216 params.mr_argc = 0;
217 params.mr_argl = NULL;
218 params.mr_argv = NULL;
5eaef520 219
85330553 220 if ((status = mr_do_call(&params, &reply)) == MR_SUCCESS)
221 status = reply.u.mr_status;
5eaef520 222
223 mr_destroy_reply(reply);
224
225 return status;
6c00b7c4 226}
85330553 227
228
229/* Server side */
230
231int mr_listen(char *port)
232{
233 struct sockaddr_in sin;
234 int s, on = 1;
235
236 memset(&sin, 0, sizeof(sin));
237 if (port[0] == '#')
238 sin.sin_port = atoi(port + 1);
239 else
240 {
241 struct servent *s;
242 s = getservbyname(port, "tcp");
243 if (s)
244 sin.sin_port = s->s_port;
245 else
246 return -1;
247 }
248
249 s = socket(AF_INET, SOCK_STREAM, 0);
250 if (s < 0)
251 return -1;
252 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int)) < 0)
253 {
254 close(s);
255 return -1;
256 }
257 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
258 {
259 close(s);
260 return -1;
261 }
262 if (listen(s, 5) < 0)
263 {
264 close(s);
265 return -1;
266 }
267
268 return s;
269}
270
271int mr_accept(int s, struct sockaddr_in *sin)
272{
273 int conn, addrlen = sizeof(struct sockaddr_in);
274 char lbuf[4], *buf;
275 long len, size, more;
276
277 conn = accept(s, (struct sockaddr *)sin, &addrlen);
278 if (conn < 0)
279 return -1;
280
281 /* Now do mrgdb accept protocol */
282 /* XXX timeout */
283
284 if (read(conn, lbuf, 4) != 4)
285 {
286 close(conn);
287 return -1;
288 }
289 getlong(lbuf, len);
290
291 buf = malloc(len);
292 if (!buf || len < 54)
293 {
294 close(conn);
295 free(buf);
296 return -1;
297 }
298
299 for (size = 0; size < len; size += more)
300 {
301 more = read(conn, buf + size, len - size);
302 if (!more)
303 break;
304 }
305 if (size != len)
306 {
307 close(conn);
308 free(buf);
309 return 0;
310 }
311
312 if (memcmp(buf, challenge + 4, 34))
313 {
314 close(conn);
315 free(buf);
316 return 0;
317 }
318
319 /* good enough */
320 free(buf);
321
322 if (write(conn, response, sizeof(response)) != sizeof(response))
323 {
324 close(conn);
325 return -1;
326 }
327 return conn;
328}
This page took 0.134001 seconds and 5 git commands to generate.