3 * This routine is part of the client library. It handles
4 * creating a connection to the moira server.
6 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
11 #include <mit-copyright.h>
13 #include <moira_site.h>
14 #include "mr_private.h"
16 #include <sys/types.h>
17 #include <sys/socket.h>
19 #include <netinet/in.h>
34 static char *mr_server_host = NULL;
36 /* mrgdb compatibility magic
38 The data looks like this:
41 00000036 [length of rest of packet]
42 00000004 [number of fields]
43 01 01 01 01 [types of fields: 4 strings]
44 "server_id\0parms\0host\0user\0" [field names]
45 00000001 [length of null-terminated server_id]
46 "\0" [server_id: ignored anyway]
47 00000001 [length of null-terminated parms]
48 "\0" [parms: ignored anyway]
49 00000001 [length of null-terminated client host]
50 "\0" [host: ignored anyway]
51 00000001 [length of null-terminated client name]
52 "\0" [user: ignored anyway]
55 00000031 [length of rest of packet]
56 00000003 [number of fields]
57 00 01 01 [types of fields: int and 2 strings]
58 "disposition\0server_id\0parms\0" [field names]
59 00000001 [GDB_ACCEPTED]
60 00000001 [length of null-terminated server_id]
61 "\0" [server_id: ignored anyway]
62 00000001 [length of null-terminated parms]
63 "\0" [parms: ignored anyway]
67 static 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";
68 static 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";
71 * Open a connection to the moira server. Looks for the server name
72 * 1) passed as an argument, 2) in environment variable, 3) by hesiod
73 * 4) compiled in default
76 int mr_connect(char *server)
78 char *port, **pp, *sbuf = NULL;
81 return MR_ALREADY_CONNECTED;
85 if (!server || (strlen(server) == 0))
86 server = getenv("MOIRASERVER");
89 if (!server || (strlen(server) == 0))
91 pp = hes_resolve("moira", "sloc");
97 if (!server || (strlen(server) == 0))
98 server = MOIRA_SERVER;
100 if (strchr(server, ':'))
102 int len = strcspn(server, ":");
103 sbuf = malloc(len + 1);
104 strncpy(sbuf, server, len);
106 port = strchr(server, ':') + 1;
110 port = strchr(MOIRA_SERVER, ':') + 1;
112 _mr_conn = mr_connect_internal(server, port);
115 return MR_CANT_CONNECT;
120 int mr_connect_internal(char *server, char *port)
123 struct sockaddr_in target;
124 struct hostent *shost;
125 char actualresponse[53];
127 shost = gethostbyname(server);
132 target.sin_port = htons(atoi(port + 1));
136 s = getservbyname(port, "tcp");
138 target.sin_port = s->s_port;
143 memcpy(&target.sin_addr, shost->h_addr, shost->h_length);
144 target.sin_family = shost->h_addrtype;
146 fd = socket(AF_INET, SOCK_STREAM, 0);
150 if (connect(fd, (struct sockaddr *)&target, sizeof(target)) < 0)
156 /* Do magic mrgdb initialization */
157 size = write(fd, challenge, sizeof(challenge));
158 if (size != sizeof(challenge))
163 for (size = 0; size < sizeof(actualresponse); size += more)
165 more = read(fd, actualresponse + size, sizeof(actualresponse) - size);
169 if (size != sizeof(actualresponse))
174 if (memcmp(actualresponse, response, sizeof(actualresponse)))
180 mr_server_host = strdup(shost->h_name);
186 int mr_disconnect(void)
191 free(mr_server_host);
192 mr_server_host = NULL;
196 int mr_host(char *host, int size)
200 /* If we are connected, mr_server_host points to a valid string. */
201 strncpy(host, mr_server_host, size);
202 host[size - 1] = '\0';
209 mr_params params, reply;
212 params.u.mr_procno = MR_NOOP;
214 params.mr_argl = NULL;
215 params.mr_argv = NULL;
217 if ((status = mr_do_call(¶ms, &reply)) == MR_SUCCESS)
218 status = reply.u.mr_status;
220 mr_destroy_reply(reply);
228 int mr_listen(char *port)
230 struct sockaddr_in sin;
233 memset(&sin, 0, sizeof(sin));
235 sin.sin_port = atoi(port + 1);
239 s = getservbyname(port, "tcp");
241 sin.sin_port = s->s_port;
246 s = socket(AF_INET, SOCK_STREAM, 0);
249 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int)) < 0)
254 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
259 if (listen(s, 5) < 0)
268 /* mr_accept returns -1 on accept() error, 0 on bad connection,
269 or connection fd on success */
271 int mr_accept(int s, struct sockaddr_in *sin)
273 int conn = -1, addrlen = sizeof(struct sockaddr_in), nread, status;
278 conn = accept(s, (struct sockaddr *)sin, &addrlen);
279 if (conn < 0 && errno != EINTR
288 status = mr_cont_accept(conn, &buf, &nread);
289 while (status == -1);
294 /* mr_cont_accept returns 0 if it has failed, an fd if it has succeeded,
295 or -1 if it is still making progress */
297 int mr_cont_accept(int conn, char **buf, int *nread)
304 if (read(conn, lbuf, 4) != 4)
313 if (!*buf || len < 58)
326 more = read(conn, *buf + *nread, len - *nread);
328 if (more == -1 && errno != EINTR)
340 if (memcmp(*buf + 4, challenge + 4, 34))
350 if (write(conn, response, sizeof(response)) != sizeof(response))