]> andersk Git - moira.git/blame - lib/mr_connect.c
Put LPRng auth, remote_support, az, xn fields into printcap, depending
[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
ea0caf4a 27#ifdef HAVE_HESIOD
a43ce477 28#include <hesiod.h>
ea0caf4a 29#endif
05fb8281 30
7ac48069 31RCSID("$Header$");
32
85330553 33int _mr_conn = 0;
34static char *mr_server_host = NULL;
35
36/* mrgdb compatibility magic
37
38 The data looks like this:
39
40 client -> server
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]
53
54 server -> client
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]
64
65*/
66
67static 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";
68static 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 69
70/*
85330553 71 * Open a connection to the moira server. Looks for the server name
5450e3a1 72 * 1) passed as an argument, 2) in environment variable, 3) by hesiod
85330553 73 * 4) compiled in default
e2a67c78 74 */
75
5eaef520 76int mr_connect(char *server)
e2a67c78 77{
85330553 78 char *port, **pp, *sbuf = NULL;
5eaef520 79
5eaef520 80 if (_mr_conn)
81 return MR_ALREADY_CONNECTED;
85330553 82 if (!mr_inited)
83 mr_init();
5eaef520 84
85 if (!server || (strlen(server) == 0))
86 server = getenv("MOIRASERVER");
5450e3a1 87
ea0caf4a 88#ifdef HAVE_HESIOD
5eaef520 89 if (!server || (strlen(server) == 0))
90 {
91 pp = hes_resolve("moira", "sloc");
92 if (pp)
93 server = *pp;
5450e3a1 94 }
a43ce477 95#endif
5450e3a1 96
5eaef520 97 if (!server || (strlen(server) == 0))
98 server = MOIRA_SERVER;
5450e3a1 99
85330553 100 if (strchr(server, ':'))
5eaef520 101 {
85330553 102 int len = strcspn(server, ":");
103 sbuf = malloc(len + 1);
104 strncpy(sbuf, server, len);
b59b20cd 105 sbuf[len] = '\0';
85330553 106 port = strchr(server, ':') + 1;
b59b20cd 107 server = sbuf;
85330553 108 }
109 else
110 port = strchr(MOIRA_SERVER, ':') + 1;
111
112 _mr_conn = mr_connect_internal(server, port);
113 free(sbuf);
114 if (!_mr_conn)
115 return MR_CANT_CONNECT;
116
85330553 117 return MR_SUCCESS;
118}
119
120int mr_connect_internal(char *server, char *port)
121{
122 int fd, size, more;
123 struct sockaddr_in target;
124 struct hostent *shost;
125 char actualresponse[53];
126
127 shost = gethostbyname(server);
128 if (!shost)
129 return 0;
130
131 if (port[0] == '#')
b59b20cd 132 target.sin_port = htons(atoi(port + 1));
85330553 133 else
134 {
135 struct servent *s;
136 s = getservbyname(port, "tcp");
137 if (s)
138 target.sin_port = s->s_port;
139 else
140 return 0;
5450e3a1 141 }
142
85330553 143 memcpy(&target.sin_addr, shost->h_addr, shost->h_length);
144 target.sin_family = shost->h_addrtype;
145
146 fd = socket(AF_INET, SOCK_STREAM, 0);
147 if (fd < 0)
148 return 0;
149
150 if (connect(fd, (struct sockaddr *)&target, sizeof(target)) < 0)
5eaef520 151 {
85330553 152 close(fd);
153 return 0;
83e80378 154 }
05fb8281 155
85330553 156 /* Do magic mrgdb initialization */
157 size = write(fd, challenge, sizeof(challenge));
158 if (size != sizeof(challenge))
159 {
160 close(fd);
161 return 0;
162 }
163 for (size = 0; size < sizeof(actualresponse); size += more)
164 {
165 more = read(fd, actualresponse + size, sizeof(actualresponse) - size);
12cbd6bd 166 if (more <= 0)
85330553 167 break;
168 }
169 if (size != sizeof(actualresponse))
170 {
171 close(fd);
172 return 0;
173 }
174 if (memcmp(actualresponse, response, sizeof(actualresponse)))
175 {
176 close(fd);
177 return 0;
178 }
05fb8281 179
b59b20cd 180 mr_server_host = strdup(shost->h_name);
181
85330553 182 /* You win */
183 return fd;
e2a67c78 184}
5eaef520 185
186int mr_disconnect(void)
e2a67c78 187{
5eaef520 188 CHECK_CONNECTED;
85330553 189 close(_mr_conn);
190 _mr_conn = 0;
5eaef520 191 free(mr_server_host);
85330553 192 mr_server_host = NULL;
193 return MR_SUCCESS;
e2a67c78 194}
195
5eaef520 196int mr_host(char *host, int size)
05fb8281 197{
5eaef520 198 CHECK_CONNECTED;
05fb8281 199
5eaef520 200 /* If we are connected, mr_server_host points to a valid string. */
201 strncpy(host, mr_server_host, size);
85330553 202 host[size - 1] = '\0';
203 return MR_SUCCESS;
05fb8281 204}
205
5eaef520 206int mr_noop(void)
e2a67c78 207{
5eaef520 208 int status;
85330553 209 mr_params params, reply;
5eaef520 210
211 CHECK_CONNECTED;
85330553 212 params.u.mr_procno = MR_NOOP;
213 params.mr_argc = 0;
214 params.mr_argl = NULL;
215 params.mr_argv = NULL;
5eaef520 216
85330553 217 if ((status = mr_do_call(&params, &reply)) == MR_SUCCESS)
218 status = reply.u.mr_status;
5eaef520 219
220 mr_destroy_reply(reply);
221
222 return status;
6c00b7c4 223}
85330553 224
225
226/* Server side */
227
228int mr_listen(char *port)
229{
230 struct sockaddr_in sin;
231 int s, on = 1;
232
233 memset(&sin, 0, sizeof(sin));
234 if (port[0] == '#')
235 sin.sin_port = atoi(port + 1);
236 else
237 {
238 struct servent *s;
239 s = getservbyname(port, "tcp");
240 if (s)
241 sin.sin_port = s->s_port;
242 else
243 return -1;
244 }
245
246 s = socket(AF_INET, SOCK_STREAM, 0);
247 if (s < 0)
248 return -1;
249 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int)) < 0)
250 {
251 close(s);
252 return -1;
253 }
254 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
255 {
256 close(s);
257 return -1;
258 }
259 if (listen(s, 5) < 0)
260 {
261 close(s);
262 return -1;
263 }
264
265 return s;
266}
267
12cbd6bd 268/* mr_accept returns -1 on accept() error, 0 on bad connection,
269 or connection fd on success */
270
85330553 271int mr_accept(int s, struct sockaddr_in *sin)
272{
78eea87c 273 int conn = -1, addrlen = sizeof(struct sockaddr_in), nread, status;
767253c8 274 char *buf = NULL;
85330553 275
78eea87c 276 while (conn < 0)
277 {
278 conn = accept(s, (struct sockaddr *)sin, &addrlen);
6f68e127 279 if (conn < 0 && errno != EINTR && errno != ERESTART)
78eea87c 280 return -1;
281 }
85330553 282
12cbd6bd 283 do
284 status = mr_cont_accept(conn, &buf, &nread);
285 while (status == -1);
85330553 286
12cbd6bd 287 return status;
288}
85330553 289
88381def 290/* mr_cont_accept returns 0 if it has failed, an fd if it has succeeded,
291 or -1 if it is still making progress */
292
12cbd6bd 293int mr_cont_accept(int conn, char **buf, int *nread)
294{
295 long len, more;
296
297 if (!*buf)
85330553 298 {
12cbd6bd 299 char lbuf[4];
300 if (read(conn, lbuf, 4) != 4)
301 {
302 close(conn);
88381def 303 return 0;
12cbd6bd 304 }
305 getlong(lbuf, len);
306 len += 4;
307
308 *buf = malloc(len);
309 if (!*buf || len < 58)
310 {
311 close(conn);
767253c8 312 free(*buf);
12cbd6bd 313 return 0;
314 }
315 putlong(*buf, len);
316 *nread = 4;
85330553 317 return -1;
318 }
12cbd6bd 319 else
320 getlong(*buf, len);
85330553 321
12cbd6bd 322 more = read(conn, *buf + *nread, len - *nread);
323
324 if (more == -1 && errno != EINTR)
85330553 325 {
326 close(conn);
12cbd6bd 327 free(*buf);
85330553 328 return 0;
329 }
330
12cbd6bd 331 *nread += more;
332
333 if (*nread != len)
334 return -1;
335
336 if (memcmp(*buf + 4, challenge + 4, 34))
85330553 337 {
338 close(conn);
12cbd6bd 339 free(*buf);
85330553 340 return 0;
341 }
342
343 /* good enough */
12cbd6bd 344 free(*buf);
85330553 345
346 if (write(conn, response, sizeof(response)) != sizeof(response))
347 {
348 close(conn);
12cbd6bd 349 return 0;
85330553 350 }
351 return conn;
352}
This page took 0.163738 seconds and 5 git commands to generate.