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>
32 static char *mr_server_host = NULL;
34 /* mrgdb compatibility magic
36 The data looks like this:
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]
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]
65 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";
66 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";
69 * Open a connection to the moira server. Looks for the server name
70 * 1) passed as an argument, 2) in environment variable, 3) by hesiod
71 * 4) compiled in default
74 int mr_connect(char *server)
76 char *port, **pp, *sbuf = NULL;
77 struct hostent *shost;
80 return MR_ALREADY_CONNECTED;
84 if (!server || (strlen(server) == 0))
85 server = getenv("MOIRASERVER");
88 if (!server || (strlen(server) == 0))
90 pp = hes_resolve("moira", "sloc");
96 if (!server || (strlen(server) == 0))
97 server = MOIRA_SERVER;
99 shost = gethostbyname(server);
101 return MR_CANT_CONNECT;
103 if (strchr(server, ':'))
105 int len = strcspn(server, ":");
106 sbuf = malloc(len + 1);
107 strncpy(sbuf, server, len);
108 sbuf[len - 1] = '\0';
110 port = strchr(server, ':') + 1;
113 port = strchr(MOIRA_SERVER, ':') + 1;
115 _mr_conn = mr_connect_internal(server, port);
118 return MR_CANT_CONNECT;
120 /* stash hostname for later use */
121 mr_server_host = strdup(shost->h_name);
125 int mr_connect_internal(char *server, char *port)
128 struct sockaddr_in target;
129 struct hostent *shost;
130 char actualresponse[53];
132 shost = gethostbyname(server);
137 target.sin_port = atoi(port + 1);
141 s = getservbyname(port, "tcp");
143 target.sin_port = s->s_port;
148 memcpy(&target.sin_addr, shost->h_addr, shost->h_length);
149 target.sin_family = shost->h_addrtype;
151 fd = socket(AF_INET, SOCK_STREAM, 0);
155 if (connect(fd, (struct sockaddr *)&target, sizeof(target)) < 0)
161 /* Do magic mrgdb initialization */
162 size = write(fd, challenge, sizeof(challenge));
163 if (size != sizeof(challenge))
168 for (size = 0; size < sizeof(actualresponse); size += more)
170 more = read(fd, actualresponse + size, sizeof(actualresponse) - size);
174 if (size != sizeof(actualresponse))
179 if (memcmp(actualresponse, response, sizeof(actualresponse)))
189 int mr_disconnect(void)
194 free(mr_server_host);
195 mr_server_host = NULL;
199 int mr_host(char *host, int size)
203 /* If we are connected, mr_server_host points to a valid string. */
204 strncpy(host, mr_server_host, size);
205 host[size - 1] = '\0';
212 mr_params params, reply;
215 params.u.mr_procno = MR_NOOP;
217 params.mr_argl = NULL;
218 params.mr_argv = NULL;
220 if ((status = mr_do_call(¶ms, &reply)) == MR_SUCCESS)
221 status = reply.u.mr_status;
223 mr_destroy_reply(reply);
231 int mr_listen(char *port)
233 struct sockaddr_in sin;
236 memset(&sin, 0, sizeof(sin));
238 sin.sin_port = atoi(port + 1);
242 s = getservbyname(port, "tcp");
244 sin.sin_port = s->s_port;
249 s = socket(AF_INET, SOCK_STREAM, 0);
252 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int)) < 0)
257 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
262 if (listen(s, 5) < 0)
271 int mr_accept(int s, struct sockaddr_in *sin)
273 int conn, addrlen = sizeof(struct sockaddr_in);
275 long len, size, more;
277 conn = accept(s, (struct sockaddr *)sin, &addrlen);
281 /* Now do mrgdb accept protocol */
284 if (read(conn, lbuf, 4) != 4)
292 if (!buf || len < 54)
299 for (size = 0; size < len; size += more)
301 more = read(conn, buf + size, len - size);
312 if (memcmp(buf, challenge + 4, 34))
322 if (write(conn, response, sizeof(response)) != sizeof(response))