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;
79 struct hostent *shost;
82 return MR_ALREADY_CONNECTED;
86 if (!server || (strlen(server) == 0))
87 server = getenv("MOIRASERVER");
90 if (!server || (strlen(server) == 0))
92 pp = hes_resolve("moira", "sloc");
98 if (!server || (strlen(server) == 0))
99 server = MOIRA_SERVER;
101 shost = gethostbyname(server);
103 return MR_CANT_CONNECT;
105 if (strchr(server, ':'))
107 int len = strcspn(server, ":");
108 sbuf = malloc(len + 1);
109 strncpy(sbuf, server, len);
110 sbuf[len - 1] = '\0';
112 port = strchr(server, ':') + 1;
115 port = strchr(MOIRA_SERVER, ':') + 1;
117 _mr_conn = mr_connect_internal(server, port);
120 return MR_CANT_CONNECT;
122 /* stash hostname for later use */
123 mr_server_host = strdup(shost->h_name);
127 int mr_connect_internal(char *server, char *port)
130 struct sockaddr_in target;
131 struct hostent *shost;
132 char actualresponse[53];
134 shost = gethostbyname(server);
139 target.sin_port = atoi(port + 1);
143 s = getservbyname(port, "tcp");
145 target.sin_port = s->s_port;
150 memcpy(&target.sin_addr, shost->h_addr, shost->h_length);
151 target.sin_family = shost->h_addrtype;
153 fd = socket(AF_INET, SOCK_STREAM, 0);
157 if (connect(fd, (struct sockaddr *)&target, sizeof(target)) < 0)
163 /* Do magic mrgdb initialization */
164 size = write(fd, challenge, sizeof(challenge));
165 if (size != sizeof(challenge))
170 for (size = 0; size < sizeof(actualresponse); size += more)
172 more = read(fd, actualresponse + size, sizeof(actualresponse) - size);
176 if (size != sizeof(actualresponse))
181 if (memcmp(actualresponse, response, sizeof(actualresponse)))
191 int mr_disconnect(void)
196 free(mr_server_host);
197 mr_server_host = NULL;
201 int mr_host(char *host, int size)
205 /* If we are connected, mr_server_host points to a valid string. */
206 strncpy(host, mr_server_host, size);
207 host[size - 1] = '\0';
214 mr_params params, reply;
217 params.u.mr_procno = MR_NOOP;
219 params.mr_argl = NULL;
220 params.mr_argv = NULL;
222 if ((status = mr_do_call(¶ms, &reply)) == MR_SUCCESS)
223 status = reply.u.mr_status;
225 mr_destroy_reply(reply);
233 int mr_listen(char *port)
235 struct sockaddr_in sin;
238 memset(&sin, 0, sizeof(sin));
240 sin.sin_port = atoi(port + 1);
244 s = getservbyname(port, "tcp");
246 sin.sin_port = s->s_port;
251 s = socket(AF_INET, SOCK_STREAM, 0);
254 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int)) < 0)
259 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
264 if (listen(s, 5) < 0)
273 /* mr_accept returns -1 on accept() error, 0 on bad connection,
274 or connection fd on success */
276 int mr_accept(int s, struct sockaddr_in *sin)
278 int conn, addrlen = sizeof(struct sockaddr_in), nread, status;
281 conn = accept(s, (struct sockaddr *)sin, &addrlen);
286 status = mr_cont_accept(conn, &buf, &nread);
287 while (status == -1);
292 int mr_cont_accept(int conn, char **buf, int *nread)
299 if (read(conn, lbuf, 4) != 4)
308 if (!*buf || len < 58)
321 more = read(conn, *buf + *nread, len - *nread);
323 if (more == -1 && errno != EINTR)
335 if (memcmp(*buf + 4, challenge + 4, 34))
345 if (write(conn, response, sizeof(response)) != sizeof(response))