~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kdm/backend/xdmcp.c

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright 1988, 1998  The Open Group
 
4
Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
 
5
Copyright 2001-2004 Oswald Buddenhagen <ossi@kde.org>
 
6
 
 
7
Permission to use, copy, modify, distribute, and sell this software and its
 
8
documentation for any purpose is hereby granted without fee, provided that
 
9
the above copyright notice appear in all copies and that both that
 
10
copyright notice and this permission notice appear in supporting
 
11
documentation.
 
12
 
 
13
The above copyright notice and this permission notice shall be included
 
14
in all copies or substantial portions of the Software.
 
15
 
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
17
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
18
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
19
IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
20
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
21
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
22
OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
Except as contained in this notice, the name of a copyright holder shall
 
25
not be used in advertising or otherwise to promote the sale, use or
 
26
other dealings in this Software without prior written authorization
 
27
from the copyright holder.
 
28
 
 
29
*/
 
30
 
 
31
/*
 
32
 * xdm - display manager daemon
 
33
 * Author: Keith Packard, MIT X Consortium
 
34
 *
 
35
 * xdmcp.c - Support for XDMCP
 
36
 */
 
37
 
 
38
#include "dm.h"
 
39
#include "dm_error.h"
 
40
#include "dm_auth.h"
 
41
#include "dm_socket.h"
 
42
 
 
43
#include <sys/types.h>
 
44
#include <ctype.h>
 
45
 
 
46
#include <netdb.h>
 
47
#if defined(IPv6) && defined(AF_INET6)
 
48
# include <arpa/inet.h>
 
49
#endif
 
50
 
 
51
 
 
52
char *
 
53
networkAddressToHostname(CARD16 connectionType, ARRAY8Ptr connectionAddress)
 
54
{
 
55
    switch (connectionType) {
 
56
    case FamilyInternet:
 
57
#if defined(IPv6) && defined(AF_INET6)
 
58
    case FamilyInternet6:
 
59
#endif
 
60
        {
 
61
            struct hostent *he;
 
62
            char *myDot, *name, *lname;
 
63
            int af_type;
 
64
#if defined(IPv6) && defined(AF_INET6)
 
65
            char dotted[INET6_ADDRSTRLEN];
 
66
 
 
67
            if (connectionType == FamilyInternet6)
 
68
                af_type = AF_INET6;
 
69
            else
 
70
#endif
 
71
                af_type = AF_INET;
 
72
 
 
73
            he = gethostbyaddr((char *)connectionAddress->data,
 
74
                               connectionAddress->length, af_type);
 
75
            if (he) {
 
76
#if defined(IPv6) && defined(AF_INET6)
 
77
                struct addrinfo *ai, *nai;
 
78
                if (!getaddrinfo(he->h_name, 0, 0, &ai)) {
 
79
                    for (nai = ai; nai; nai = nai->ai_next) {
 
80
                        if (af_type == nai->ai_family &&
 
81
                            !memcmp(nai->ai_family == AF_INET ?
 
82
                                    (char *)&((struct sockaddr_in *)nai->ai_addr)->sin_addr :
 
83
                                    (char *)&((struct sockaddr_in6 *)nai->ai_addr)->sin6_addr,
 
84
                                    connectionAddress->data,
 
85
                                    connectionAddress->length))
 
86
                        {
 
87
                            freeaddrinfo(ai);
 
88
                            goto oki;
 
89
                        }
 
90
                    }
 
91
                    freeaddrinfo(ai);
 
92
#else
 
93
                if ((he = gethostbyname(he->h_name)) &&
 
94
                    he->h_addrtype == AF_INET)
 
95
                {
 
96
                    int i;
 
97
                    for (i = 0; he->h_addr_list[i]; i++)
 
98
                        if (!memcmp(he->h_addr_list[i],
 
99
                                    connectionAddress->data, 4))
 
100
                            goto oki;
 
101
#endif
 
102
                    logError("DNS spoof attempt or misconfigured resolver.\n");
 
103
                }
 
104
                goto gotnone;
 
105
              oki:
 
106
                if (strDup(&name, he->h_name) &&
 
107
                    !strchr(name, '.') &&
 
108
                    (myDot = strchr(localHostname(), '.')))
 
109
                {
 
110
                    if (ASPrintf(&lname, "%s%s", name, myDot)) {
 
111
#if defined(IPv6) && defined(AF_INET6)
 
112
                        if (!getaddrinfo(lname, 0, 0, &ai)) {
 
113
                            for (nai = ai; nai; nai = nai->ai_next) {
 
114
                                if (af_type == nai->ai_family &&
 
115
                                    !memcmp(nai->ai_family == AF_INET ?
 
116
                                            (char *)&((struct sockaddr_in *)nai->ai_addr)->sin_addr :
 
117
                                            (char *)&((struct sockaddr_in6 *)nai->ai_addr)->sin6_addr,
 
118
                                            connectionAddress->data,
 
119
                                            connectionAddress->length)) {
 
120
                                    freeaddrinfo(ai);
 
121
                                    free(name);
 
122
                                    return lname;
 
123
                                }
 
124
                            }
 
125
                            freeaddrinfo(ai);
 
126
                        }
 
127
#else
 
128
                        if ((he = gethostbyname(lname)) && he->h_addrtype == AF_INET) {
 
129
                            int i;
 
130
                            for (i = 0; he->h_addr_list[i]; i++)
 
131
                                if (!memcmp(he->h_addr_list[i], connectionAddress->data, 4)) {
 
132
                                    free(name);
 
133
                                    return lname;
 
134
                                }
 
135
                        }
 
136
#endif
 
137
                        free(lname);
 
138
                    }
 
139
                }
 
140
            } else {
 
141
              gotnone:
 
142
                /* can't get name, so use emergency fallback */
 
143
#if defined(IPv6) && defined(AF_INET6)
 
144
                inet_ntop(af_type, connectionAddress->data,
 
145
                          dotted, sizeof(dotted));
 
146
                strDup(&name, dotted);
 
147
#else
 
148
                ASPrintf(&name, "%[4|'.'hhu", connectionAddress->data);
 
149
#endif
 
150
                logWarn("Cannot convert Internet address %s to host name\n", name);
 
151
            }
 
152
            return name;
 
153
        }
 
154
#ifdef DNET
 
155
    case FamilyDECnet:
 
156
        break;
 
157
#endif /* DNET */
 
158
    default:
 
159
        break;
 
160
    }
 
161
    return 0;
 
162
}
 
163
 
 
164
static char *
 
165
networkAddressToName(CARD16 connectionType, ARRAY8Ptr connectionAddress,
 
166
                     struct sockaddr *originalAddress, CARD16 displayNumber)
 
167
{
 
168
    switch (connectionType) {
 
169
    case FamilyInternet:
 
170
#if defined(IPv6) && defined(AF_INET6)
 
171
    case FamilyInternet6:
 
172
#endif
 
173
        {
 
174
            CARD8 *data;
 
175
            struct hostent *hostent;
 
176
            char *hostname = 0;
 
177
            char *name;
 
178
            const char *localhost;
 
179
            int multiHomed = False;
 
180
            int type;
 
181
#if defined(IPv6) && defined(AF_INET6)
 
182
            struct addrinfo *ai = 0, *nai, hints;
 
183
            char  dotted[INET6_ADDRSTRLEN];
 
184
 
 
185
            if (connectionType == FamilyInternet6)
 
186
                type = AF_INET6;
 
187
            else
 
188
#endif
 
189
                type = AF_INET;
 
190
 
 
191
            data = connectionAddress->data;
 
192
            hostent = gethostbyaddr((char *)data,
 
193
                                    connectionAddress->length, type);
 
194
            if (hostent) {
 
195
                if (sourceAddress) {
 
196
#if defined(IPv6) && defined(AF_INET6)
 
197
                    bzero(&hints, sizeof(hints));
 
198
                    hints.ai_flags = AI_CANONNAME;
 
199
                    if (!getaddrinfo(hostent->h_name, 0, &hints, &ai)) {
 
200
                        hostname = ai->ai_canonname;
 
201
                        for (nai = ai->ai_next; nai; nai = nai->ai_next)
 
202
                            if (ai->ai_protocol == nai->ai_protocol &&
 
203
                                memcmp(ai->ai_addr, nai->ai_addr,
 
204
                                       ai->ai_addrlen))
 
205
                                multiHomed = True;
 
206
                    }
 
207
#else
 
208
                    hostent = gethostbyname(hostent->h_name);
 
209
                    if (hostent && hostent->h_addrtype == AF_INET) {
 
210
                        multiHomed = hostent->h_addr_list[1] != 0;
 
211
                        hostname = hostent->h_name;
 
212
                    }
 
213
#endif
 
214
                } else {
 
215
                    hostname = hostent->h_name;
 
216
                }
 
217
            }
 
218
 
 
219
            localhost = localHostname();
 
220
 
 
221
            /*
 
222
             * protect against bogus host names
 
223
             */
 
224
            if (hostname && *hostname && *hostname != '.' && !multiHomed) {
 
225
                if (!strcmp(localhost, hostname)) {
 
226
                    ASPrintf(&name, "localhost:%d", displayNumber);
 
227
                } else {
 
228
                    if (removeDomainname) {
 
229
                        char *localDot, *remoteDot;
 
230
 
 
231
                        /* check for a common domain name. This
 
232
                         * could reduce names by recognising common
 
233
                         * super-domain names as well, but I don't think
 
234
                         * this is as useful, and will confuse more
 
235
                         * people
 
236
                         */
 
237
                        if ((localDot = strchr(localhost, '.')) &&
 
238
                            (remoteDot = strchr(hostname, '.')))
 
239
                        {
 
240
                            /* smash the name in place; it won't
 
241
                             * be needed later.
 
242
                             */
 
243
                            if (!strcmp(localDot + 1, remoteDot + 1))
 
244
                                *remoteDot = '\0';
 
245
                        }
 
246
                    }
 
247
 
 
248
                    ASPrintf(&name, "%s:%d", hostname, displayNumber);
 
249
                }
 
250
            } else {
 
251
#if defined(IPv6) && defined(AF_INET6)
 
252
                if (multiHomed) {
 
253
                    if (connectionType == FamilyInternet) {
 
254
                        data = (CARD8 *)
 
255
                            &((struct sockaddr_in *)originalAddress)->sin_addr;
 
256
                    } else {
 
257
                        data = (CARD8 *)
 
258
                            &((struct sockaddr_in6 *)originalAddress)->sin6_addr;
 
259
                    }
 
260
                }
 
261
                inet_ntop(type, data, dotted, sizeof(dotted));
 
262
                ASPrintf(&name, "%s:%d", dotted, displayNumber);
 
263
#else
 
264
                if (multiHomed)
 
265
                    data = (CARD8 *)
 
266
                        &((struct sockaddr_in *)originalAddress)->sin_addr;
 
267
                ASPrintf(&name, "%[4|'.'hhu:%d", data, displayNumber);
 
268
#endif
 
269
            }
 
270
#if defined(IPv6) && defined(AF_INET6)
 
271
            if (ai)
 
272
                freeaddrinfo(ai);
 
273
#endif
 
274
            return name;
 
275
        }
 
276
#ifdef DNET
 
277
    case FamilyDECnet:
 
278
        return 0;
 
279
#endif /* DNET */
 
280
    default:
 
281
        return 0;
 
282
    }
 
283
}
 
284
 
 
285
static void
 
286
convertClientAddress(struct sockaddr *from,
 
287
                     ARRAY8Ptr addr, /* return */
 
288
                     ARRAY8Ptr port, /* return */
 
289
                     CARD16 *type) /* return */
 
290
{
 
291
    int length, family;
 
292
    CARD8 *data;
 
293
 
 
294
    data = netaddrPort((XdmcpNetaddr)from, &length);
 
295
    XdmcpAllocARRAY8(port, length);
 
296
    memmove(port->data, data, length);
 
297
    port->length = length;
 
298
 
 
299
    family = convertAddr((XdmcpNetaddr)from, &length, &data);
 
300
    XdmcpAllocARRAY8(addr, length);
 
301
    memmove(addr->data, data, length);
 
302
    addr->length = length;
 
303
 
 
304
    *type = family;
 
305
}
 
306
 
 
307
static XdmcpBuffer buffer;
 
308
 
 
309
static ARRAY8 Hostname;
 
310
static unsigned long globalSessionID;
 
311
 
 
312
#define nextSessionID() (++globalSessionID)
 
313
 
 
314
void initXdmcp(void)
 
315
{
 
316
    /* Set randomly so we are unlikely to reuse id's from a previous
 
317
     * incarnation so we don't say "Alive" to those displays.
 
318
     * Start with low digits 0 to make debugging easier.
 
319
     */
 
320
    globalSessionID = (time((time_t *)0) & 0x7fff) * 16000;
 
321
 
 
322
    Hostname.data = (unsigned char *)localHostname();
 
323
    Hostname.length = strlen((char *)Hostname.data);
 
324
}
 
325
 
 
326
static void
 
327
send_willing(struct sockaddr *from, int fromlen,
 
328
             ARRAY8Ptr authenticationName, ARRAY8Ptr status, int fd)
 
329
{
 
330
    XdmcpHeader header;
 
331
 
 
332
    debug("send <willing> %.*s %.*s\n", authenticationName->length,
 
333
          authenticationName->data,
 
334
          status->length,
 
335
          status->data);
 
336
    header.version = XDM_PROTOCOL_VERSION;
 
337
    header.opcode = (CARD16)WILLING;
 
338
    header.length =
 
339
        6 + authenticationName->length + Hostname.length + status->length;
 
340
    XdmcpWriteHeader(&buffer, &header);
 
341
    XdmcpWriteARRAY8(&buffer, authenticationName);
 
342
    XdmcpWriteARRAY8(&buffer, &Hostname);
 
343
    XdmcpWriteARRAY8(&buffer, status);
 
344
    XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
 
345
}
 
346
 
 
347
static void
 
348
send_unwilling(struct sockaddr *from, int fromlen,
 
349
               ARRAY8Ptr authenticationName, ARRAY8Ptr status, int fd)
 
350
{
 
351
    XdmcpHeader header;
 
352
 
 
353
    debug("send <unwilling> %.*s %.*s\n", authenticationName->length,
 
354
          authenticationName->data,
 
355
          status->length,
 
356
          status->data);
 
357
    header.version = XDM_PROTOCOL_VERSION;
 
358
    header.opcode = (CARD16)UNWILLING;
 
359
    header.length = 4 + Hostname.length + status->length;
 
360
    XdmcpWriteHeader(&buffer, &header);
 
361
    XdmcpWriteARRAY8(&buffer, &Hostname);
 
362
    XdmcpWriteARRAY8(&buffer, status);
 
363
    XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
 
364
}
 
365
 
 
366
static void
 
367
all_query_respond(struct sockaddr *from, int fromlen,
 
368
                  ARRAYofARRAY8Ptr authenticationNames,
 
369
                  xdmOpCode type, int fd)
 
370
{
 
371
    ARRAY8Ptr authenticationName;
 
372
    ARRAY8 status;
 
373
    ARRAY8 addr;
 
374
    ARRAY8 port;
 
375
    CARD16 connectionType;
 
376
    int family;
 
377
    int length;
 
378
 
 
379
    family = convertAddr((XdmcpNetaddr)from, &length, &addr.data);
 
380
    addr.length = length; /* convert int to short */
 
381
    port.data = netaddrPort((XdmcpNetaddr)from, &length);
 
382
    port.length = length; /* convert int to short */
 
383
    debug("all_query_respond: conntype=%d, addr=%02[*:hhx\n",
 
384
          family, addr.length, addr.data);
 
385
    if (family < 0)
 
386
        return;
 
387
    connectionType = family;
 
388
 
 
389
    if (type == INDIRECT_QUERY)
 
390
        registerIndirectChoice(&addr, &port, connectionType, 0);
 
391
    else
 
392
        checkIndirectChoice(&addr, &port, connectionType);
 
393
 
 
394
    authenticationName = chooseAuthentication(authenticationNames);
 
395
    if (isWilling(&addr, connectionType, authenticationName, &status, type))
 
396
        send_willing(from, fromlen, authenticationName, &status, fd);
 
397
    else
 
398
        if (type == QUERY)
 
399
            send_unwilling(from, fromlen, authenticationName, &status, fd);
 
400
    XdmcpDisposeARRAY8(&status);
 
401
}
 
402
 
 
403
static void
 
404
sendForward(CARD16 connectionType, ARRAY8Ptr address, char *closure)
 
405
{
 
406
#ifdef AF_INET
 
407
    struct sockaddr_in in_addr;
 
408
#endif
 
409
#if defined(IPv6) && defined(AF_INET6)
 
410
    struct sockaddr_in6 in6_addr;
 
411
#endif
 
412
#ifdef AF_DECnet
 
413
#endif
 
414
    struct sockaddr *addr;
 
415
    int addrlen;
 
416
 
 
417
    switch (connectionType) {
 
418
#ifdef AF_INET
 
419
    case FamilyInternet:
 
420
        addr = (struct sockaddr *)&in_addr;
 
421
        bzero((char *)&in_addr, sizeof(in_addr));
 
422
# ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
 
423
        in_addr.sin_len = sizeof(in_addr);
 
424
# endif
 
425
        in_addr.sin_family = AF_INET;
 
426
        in_addr.sin_port = htons((short)requestPort);
 
427
        if (address->length != 4)
 
428
            return;
 
429
        memmove(&in_addr.sin_addr, address->data, address->length);
 
430
        addrlen = sizeof(struct sockaddr_in);
 
431
        break;
 
432
#endif
 
433
#if defined(IPv6) && defined(AF_INET6)
 
434
    case FamilyInternet6:
 
435
        addr = (struct sockaddr *)&in6_addr;
 
436
        bzero(&in6_addr, sizeof(in6_addr));
 
437
# ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
 
438
        in6_addr.sin6_len = sizeof(in6_addr);
 
439
# endif
 
440
        in6_addr.sin6_family = AF_INET6;
 
441
        in6_addr.sin6_port = htons((short)requestPort);
 
442
        if (address->length != 16)
 
443
            return;
 
444
        memmove(&in6_addr.sin6_addr, address->data, address->length);
 
445
        addrlen = sizeof(struct sockaddr_in6);
 
446
        break;
 
447
#endif
 
448
#ifdef AF_DECnet
 
449
    case FamilyDECnet:
 
450
#endif
 
451
    default:
 
452
        return;
 
453
    }
 
454
    XdmcpFlush((int)(long)closure, &buffer, (XdmcpNetaddr)addr, addrlen);
 
455
    return;
 
456
}
 
457
 
 
458
static void
 
459
indirect_respond(struct sockaddr *from, int fromlen, int length, int fd)
 
460
{
 
461
    ARRAYofARRAY8 queryAuthenticationNames;
 
462
    ARRAY8 clientAddress;
 
463
    ARRAY8 clientPort;
 
464
    CARD16 connectionType;
 
465
    int expectedLen;
 
466
    int i;
 
467
    XdmcpHeader header;
 
468
    int localHostAsWell;
 
469
 
 
470
    debug("<indirect> respond %d\n", length);
 
471
    if (!XdmcpReadARRAYofARRAY8(&buffer, &queryAuthenticationNames))
 
472
        return;
 
473
    expectedLen = 1;
 
474
    for (i = 0; i < (int)queryAuthenticationNames.length; i++)
 
475
        expectedLen += 2 + queryAuthenticationNames.data[i].length;
 
476
    if (length == expectedLen) {
 
477
        convertClientAddress(from,
 
478
                             &clientAddress, &clientPort, &connectionType);
 
479
        /*
 
480
         * set up the forward query packet
 
481
         */
 
482
        header.version = XDM_PROTOCOL_VERSION;
 
483
        header.opcode = (CARD16)FORWARD_QUERY;
 
484
        header.length = 0;
 
485
        header.length += 2 + clientAddress.length;
 
486
        header.length += 2 + clientPort.length;
 
487
        header.length += 1;
 
488
        for (i = 0; i < (int)queryAuthenticationNames.length; i++)
 
489
            header.length += 2 + queryAuthenticationNames.data[i].length;
 
490
        XdmcpWriteHeader(&buffer, &header);
 
491
        XdmcpWriteARRAY8(&buffer, &clientAddress);
 
492
        XdmcpWriteARRAY8(&buffer, &clientPort);
 
493
        XdmcpWriteARRAYofARRAY8(&buffer, &queryAuthenticationNames);
 
494
 
 
495
        localHostAsWell =
 
496
            forEachMatchingIndirectHost(&clientAddress, &clientPort, connectionType,
 
497
                                        sendForward, (char *)(long)fd);
 
498
 
 
499
        XdmcpDisposeARRAY8(&clientAddress);
 
500
        XdmcpDisposeARRAY8(&clientPort);
 
501
        if (localHostAsWell)
 
502
            all_query_respond(from, fromlen, &queryAuthenticationNames,
 
503
                              INDIRECT_QUERY, fd);
 
504
    } else
 
505
        debug("<indirect> length error got %d expect %d\n",
 
506
              length, expectedLen);
 
507
    XdmcpDisposeARRAYofARRAY8(&queryAuthenticationNames);
 
508
}
 
509
 
 
510
/*
 
511
 * respond to a request on the UDP socket.
 
512
 */
 
513
 
 
514
static void
 
515
direct_query_respond(struct sockaddr *from, int fromlen,
 
516
                     int length, xdmOpCode type, int fd)
 
517
{
 
518
    ARRAYofARRAY8 queryAuthenticationNames;
 
519
    int expectedLen;
 
520
    int i;
 
521
 
 
522
    if (!XdmcpReadARRAYofARRAY8(&buffer, &queryAuthenticationNames))
 
523
        return;
 
524
    expectedLen = 1;
 
525
    for (i = 0; i < (int)queryAuthenticationNames.length; i++)
 
526
        expectedLen += 2 + queryAuthenticationNames.data[i].length;
 
527
    if (length == expectedLen)
 
528
        all_query_respond(from, fromlen, &queryAuthenticationNames, type, fd);
 
529
    XdmcpDisposeARRAYofARRAY8(&queryAuthenticationNames);
 
530
}
 
531
 
 
532
static void
 
533
query_respond(struct sockaddr *from, int fromlen, int length, int fd)
 
534
{
 
535
    debug("<query> respond %d\n", length);
 
536
    direct_query_respond(from, fromlen, length, QUERY, fd);
 
537
}
 
538
 
 
539
static void
 
540
broadcast_respond(struct sockaddr *from, int fromlen, int length, int fd)
 
541
{
 
542
    direct_query_respond(from, fromlen, length, BROADCAST_QUERY, fd);
 
543
}
 
544
 
 
545
/*ARGSUSED*/
 
546
static void
 
547
forward_respond(struct sockaddr *from, int fromlen ATTR_UNUSED,
 
548
                int length, int fd)
 
549
{
 
550
    ARRAY8 clientAddress;
 
551
    ARRAY8 clientPort;
 
552
    ARRAYofARRAY8 authenticationNames;
 
553
    struct sockaddr *client;
 
554
    int clientlen;
 
555
    int expectedLen;
 
556
    int i;
 
557
 
 
558
    debug("<forward> respond %d\n", length);
 
559
    clientAddress.length = 0;
 
560
    clientAddress.data = 0;
 
561
    clientPort.length = 0;
 
562
    clientPort.data = 0;
 
563
    authenticationNames.length = 0;
 
564
    authenticationNames.data = 0;
 
565
    if (XdmcpReadARRAY8(&buffer, &clientAddress) &&
 
566
        XdmcpReadARRAY8(&buffer, &clientPort) &&
 
567
        XdmcpReadARRAYofARRAY8(&buffer, &authenticationNames))
 
568
    {
 
569
        expectedLen = 0;
 
570
        expectedLen += 2 + clientAddress.length;
 
571
        expectedLen += 2 + clientPort.length;
 
572
        expectedLen += 1; /* authenticationNames */
 
573
        for (i = 0; i < (int)authenticationNames.length; i++)
 
574
            expectedLen += 2 + authenticationNames.data[i].length;
 
575
        if (length == expectedLen) {
 
576
            int j;
 
577
 
 
578
            j = 0;
 
579
            for (i = 0; i < (int)clientPort.length; i++)
 
580
                j = j * 256 + clientPort.data[i];
 
581
            debug("<forward> client address (port %d) %[*hhu\n", j,
 
582
                  clientAddress.length, clientAddress.data);
 
583
            switch (from->sa_family) {
 
584
#ifdef AF_INET
 
585
            case AF_INET: {
 
586
                struct sockaddr_in in_addr;
 
587
 
 
588
                if (clientAddress.length != 4 || clientPort.length != 2)
 
589
                    goto badAddress;
 
590
                bzero(&in_addr, sizeof(in_addr));
 
591
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
 
592
                in_addr.sin_len = sizeof(in_addr);
 
593
#endif
 
594
                in_addr.sin_family = AF_INET;
 
595
                memmove(&in_addr.sin_addr, clientAddress.data, 4);
 
596
                memmove(&in_addr.sin_port, clientPort.data, 2);
 
597
                client = (struct sockaddr *)&in_addr;
 
598
                clientlen = sizeof(in_addr);
 
599
                all_query_respond(client, clientlen, &authenticationNames,
 
600
                                  FORWARD_QUERY, fd);
 
601
                break; }
 
602
#endif
 
603
#if defined(IPv6) && defined(AF_INET6)
 
604
            case AF_INET6: {
 
605
                struct sockaddr_in6 in6_addr;
 
606
 
 
607
                if ((clientAddress.length != 16 && clientAddress.length != 4) ||
 
608
                        clientPort.length != 2)
 
609
                    goto badAddress;
 
610
                bzero(&in6_addr, sizeof(in6_addr));
 
611
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
 
612
                in6_addr.sin6_len = sizeof(in6_addr);
 
613
#endif
 
614
                in6_addr.sin6_family = AF_INET6;
 
615
                if (clientAddress.length == 16) {
 
616
                    memmove(in6_addr.sin6_addr.s6_addr, clientAddress.data, 16);
 
617
                } else {
 
618
                    /* If the client wants to forward the xdm server to an
 
619
                     * IPv4 hosts it sends an IPv4 address in the forward
 
620
                     * packet. On dual-stack hosts the packet arrives as a
 
621
                     * IPv6 packet. To respond to the IPv4 host one has
 
622
                     * to create an IPv4-mapped address.
 
623
                     * One example where this is necessary is an IPv4-only
 
624
                     * thin client that connects to a dual-stacked xdm.
 
625
                     */
 
626
                    in6_addr.sin6_addr.s6_addr[10] = 0xff;
 
627
                    in6_addr.sin6_addr.s6_addr[11] = 0xff;
 
628
                    memmove(in6_addr.sin6_addr.s6_addr + 12, clientAddress.data, 4);
 
629
                }
 
630
                memmove(&in6_addr.sin6_port, clientPort.data, 2);
 
631
                client = (struct sockaddr *)&in6_addr;
 
632
                clientlen = sizeof(in6_addr);
 
633
                all_query_respond(client, clientlen, &authenticationNames,
 
634
                                  FORWARD_QUERY, fd);
 
635
                break; }
 
636
#endif
 
637
#ifdef AF_UNIX
 
638
            case AF_UNIX: {
 
639
                struct sockaddr_un un_addr;
 
640
 
 
641
                if (clientAddress.length >= sizeof(un_addr.sun_path))
 
642
                    goto badAddress;
 
643
                bzero(&un_addr, sizeof(un_addr));
 
644
                un_addr.sun_family = AF_UNIX;
 
645
                memmove(un_addr.sun_path, clientAddress.data, clientAddress.length);
 
646
                un_addr.sun_path[clientAddress.length] = '\0';
 
647
                client = (struct sockaddr *)&un_addr;
 
648
#if defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN) && !defined(__Lynx__) && defined(UNIXCONN)
 
649
                un_addr.sun_len = strlen(un_addr.sun_path);
 
650
                clientlen = SUN_LEN(&un_addr);
 
651
#else
 
652
                clientlen = sizeof(un_addr);
 
653
#endif
 
654
                all_query_respond(client, clientlen, &authenticationNames,
 
655
                                  FORWARD_QUERY, fd);
 
656
                break; }
 
657
#endif
 
658
#ifdef AF_CHAOS
 
659
            case AF_CHAOS:
 
660
                goto badAddress;
 
661
#endif
 
662
#ifdef AF_DECnet
 
663
            case AF_DECnet:
 
664
                goto badAddress;
 
665
#endif
 
666
            }
 
667
        } else {
 
668
            debug("<forward> length error got %d expect %d\n", length, expectedLen);
 
669
        }
 
670
    }
 
671
  badAddress:
 
672
    XdmcpDisposeARRAY8(&clientAddress);
 
673
    XdmcpDisposeARRAY8(&clientPort);
 
674
    XdmcpDisposeARRAYofARRAY8(&authenticationNames);
 
675
}
 
676
 
 
677
 
 
678
static void
 
679
send_accept(struct sockaddr *to, int tolen, CARD32 sessionID,
 
680
            ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData,
 
681
            ARRAY8Ptr authorizationName, ARRAY8Ptr authorizationData,
 
682
            int fd)
 
683
{
 
684
    XdmcpHeader header;
 
685
 
 
686
    debug("<accept> session ID %ld\n", (long)sessionID);
 
687
    header.version = XDM_PROTOCOL_VERSION;
 
688
    header.opcode = (CARD16)ACCEPT;
 
689
    header.length = 4; /* session ID */
 
690
    header.length += 2 + authenticationName->length;
 
691
    header.length += 2 + authenticationData->length;
 
692
    header.length += 2 + authorizationName->length;
 
693
    header.length += 2 + authorizationData->length;
 
694
    XdmcpWriteHeader(&buffer, &header);
 
695
    XdmcpWriteCARD32(&buffer, sessionID);
 
696
    XdmcpWriteARRAY8(&buffer, authenticationName);
 
697
    XdmcpWriteARRAY8(&buffer, authenticationData);
 
698
    XdmcpWriteARRAY8(&buffer, authorizationName);
 
699
    XdmcpWriteARRAY8(&buffer, authorizationData);
 
700
    XdmcpFlush(fd, &buffer, (XdmcpNetaddr)to, tolen);
 
701
}
 
702
 
 
703
static void
 
704
send_decline(struct sockaddr *to, int tolen,
 
705
             ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData,
 
706
             ARRAY8Ptr status, int fd)
 
707
{
 
708
    XdmcpHeader header;
 
709
 
 
710
    debug("<decline> %.*s\n", status->length, status->data);
 
711
    header.version = XDM_PROTOCOL_VERSION;
 
712
    header.opcode = (CARD16)DECLINE;
 
713
    header.length = 0;
 
714
    header.length += 2 + status->length;
 
715
    header.length += 2 + authenticationName->length;
 
716
    header.length += 2 + authenticationData->length;
 
717
    XdmcpWriteHeader(&buffer, &header);
 
718
    XdmcpWriteARRAY8(&buffer, status);
 
719
    XdmcpWriteARRAY8(&buffer, authenticationName);
 
720
    XdmcpWriteARRAY8(&buffer, authenticationData);
 
721
    XdmcpFlush(fd, &buffer, (XdmcpNetaddr)to, tolen);
 
722
}
 
723
 
 
724
static ARRAY8 outOfMemory = { (CARD16)13, (CARD8Ptr)"Out of memory" };
 
725
static ARRAY8 noValidAddr = { (CARD16)16, (CARD8Ptr)"No valid address" };
 
726
static ARRAY8 noValidAuth = { (CARD16)22, (CARD8Ptr)"No valid authorization" };
 
727
static ARRAY8 noAuthentic = { (CARD16)29, (CARD8Ptr)"XDM has no authentication key" };
 
728
 
 
729
static void
 
730
request_respond(struct sockaddr *from, int fromlen, int length, int fd)
 
731
{
 
732
    CARD16 displayNumber;
 
733
    ARRAY16 connectionTypes;
 
734
    ARRAYofARRAY8 connectionAddresses;
 
735
    ARRAY8 authenticationName;
 
736
    ARRAY8 authenticationData;
 
737
    ARRAYofARRAY8 authorizationNames;
 
738
    ARRAY8 manufacturerDisplayID;
 
739
    ARRAY8Ptr reason = 0;
 
740
    int expectlen;
 
741
    int i, j;
 
742
    struct protoDisplay  *pdpy;
 
743
    ARRAY8 authorizationName, authorizationData;
 
744
    ARRAY8Ptr connectionAddress;
 
745
 
 
746
    debug("<request> respond %d\n", length);
 
747
    connectionTypes.data = 0;
 
748
    connectionAddresses.data = 0;
 
749
    authenticationName.data = 0;
 
750
    authenticationData.data = 0;
 
751
    authorizationNames.data = 0;
 
752
    authorizationName.length = 0;
 
753
    authorizationData.length = 0;
 
754
    manufacturerDisplayID.data = 0;
 
755
    if (XdmcpReadCARD16(&buffer, &displayNumber) &&
 
756
        XdmcpReadARRAY16(&buffer, &connectionTypes) &&
 
757
        XdmcpReadARRAYofARRAY8(&buffer, &connectionAddresses) &&
 
758
        XdmcpReadARRAY8(&buffer, &authenticationName) &&
 
759
        XdmcpReadARRAY8(&buffer, &authenticationData) &&
 
760
        XdmcpReadARRAYofARRAY8(&buffer, &authorizationNames) &&
 
761
        XdmcpReadARRAY8(&buffer, &manufacturerDisplayID))
 
762
    {
 
763
        expectlen = 0;
 
764
        expectlen += 2; /* displayNumber */
 
765
        expectlen += 1 + 2 * connectionTypes.length; /* connectionTypes */
 
766
        expectlen += 1; /* connectionAddresses */
 
767
        for (i = 0; i < (int)connectionAddresses.length; i++)
 
768
            expectlen += 2 + connectionAddresses.data[i].length;
 
769
        expectlen += 2 + authenticationName.length; /* authenticationName */
 
770
        expectlen += 2 + authenticationData.length; /* authenticationData */
 
771
        expectlen += 1; /* authoriationNames */
 
772
        for (i = 0; i < (int)authorizationNames.length; i++)
 
773
            expectlen += 2 + authorizationNames.data[i].length;
 
774
        expectlen += 2 + manufacturerDisplayID.length; /* displayID */
 
775
        if (expectlen != length) {
 
776
            debug("<request> length error got %d expect %d\n",
 
777
                  length, expectlen);
 
778
            goto abort;
 
779
        }
 
780
        if (connectionTypes.length == 0 ||
 
781
            connectionAddresses.length != connectionTypes.length)
 
782
        {
 
783
            reason = &noValidAddr;
 
784
            pdpy = 0;
 
785
            goto decline;
 
786
        }
 
787
        pdpy = findProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber);
 
788
        if (!pdpy) {
 
789
 
 
790
            /* Check this Display against the Manager's policy */
 
791
            reason = isAccepting(from, fromlen, displayNumber);
 
792
            if (reason)
 
793
                goto decline;
 
794
 
 
795
            /* Check the Display's stream services against Manager's policy */
 
796
            i = selectConnectionTypeIndex(&connectionTypes,
 
797
                                          &connectionAddresses);
 
798
            if (i < 0) {
 
799
                reason = &noValidAddr;
 
800
                goto decline;
 
801
            }
 
802
 
 
803
            /* The Manager considers this a new session */
 
804
            connectionAddress = &connectionAddresses.data[i];
 
805
            pdpy = newProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber,
 
806
                                   connectionTypes.data[i], connectionAddress,
 
807
                                   nextSessionID());
 
808
            debug("newProtoDisplay %p\n", pdpy);
 
809
            if (!pdpy) {
 
810
                reason = &outOfMemory;
 
811
                goto decline;
 
812
            }
 
813
        }
 
814
        if (authorizationNames.length == 0)
 
815
            j = 0;
 
816
        else
 
817
            j = selectAuthorizationTypeIndex(&authenticationName,
 
818
                                             &authorizationNames);
 
819
        if (j < 0) {
 
820
            reason = &noValidAuth;
 
821
            goto decline;
 
822
        }
 
823
        if (!checkAuthentication(pdpy,
 
824
                                 &manufacturerDisplayID,
 
825
                                 &authenticationName,
 
826
                                 &authenticationData))
 
827
        {
 
828
            reason = &noAuthentic;
 
829
            goto decline;
 
830
        }
 
831
        if (j < (int)authorizationNames.length) {
 
832
            Xauth *auth;
 
833
            setProtoDisplayAuthorization(pdpy,
 
834
                                         (unsigned short)authorizationNames.data[j].length,
 
835
                                         (char *)authorizationNames.data[j].data);
 
836
            auth = pdpy->xdmcpAuthorization;
 
837
            if (!auth)
 
838
                auth = pdpy->fileAuthorization;
 
839
            if (auth) {
 
840
                authorizationName.length = auth->name_length;
 
841
                authorizationName.data = (CARD8Ptr) auth->name;
 
842
                authorizationData.length = auth->data_length;
 
843
                authorizationData.data = (CARD8Ptr) auth->data;
 
844
            }
 
845
        }
 
846
        if (pdpy) {
 
847
            send_accept(from, fromlen, pdpy->sessionID,
 
848
                        &authenticationName,
 
849
                        &authenticationData,
 
850
                        &authorizationName,
 
851
                        &authorizationData, fd);
 
852
        } else {
 
853
  decline:
 
854
            send_decline(from, fromlen, &authenticationName,
 
855
                         &authenticationData,
 
856
                         reason, fd);
 
857
            if (pdpy)
 
858
                disposeProtoDisplay(pdpy);
 
859
        }
 
860
    }
 
861
  abort:
 
862
    XdmcpDisposeARRAY16(&connectionTypes);
 
863
    XdmcpDisposeARRAYofARRAY8(&connectionAddresses);
 
864
    XdmcpDisposeARRAY8(&authenticationName);
 
865
    XdmcpDisposeARRAY8(&authenticationData);
 
866
    XdmcpDisposeARRAYofARRAY8(&authorizationNames);
 
867
    XdmcpDisposeARRAY8(&manufacturerDisplayID);
 
868
}
 
869
 
 
870
 
 
871
static void
 
872
send_failed(struct sockaddr *from, int fromlen,
 
873
            const char *name, CARD32 sessionID, const char *reason, int fd)
 
874
{
 
875
    char buf[360];
 
876
    XdmcpHeader header;
 
877
    ARRAY8 status;
 
878
 
 
879
    sprintf(buf, "Session %ld failed for display %.260s: %s",
 
880
            (long)sessionID, name, reason);
 
881
    debug("send_failed(%\"s)\n", buf);
 
882
    status.length = strlen(buf);
 
883
    status.data = (CARD8Ptr) buf;
 
884
    header.version = XDM_PROTOCOL_VERSION;
 
885
    header.opcode = (CARD16)FAILED;
 
886
    header.length = 6 + status.length;
 
887
    XdmcpWriteHeader(&buffer, &header);
 
888
    XdmcpWriteCARD32(&buffer, sessionID);
 
889
    XdmcpWriteARRAY8(&buffer, &status);
 
890
    XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
 
891
}
 
892
 
 
893
void
 
894
sendFailed(struct display *d, const char *reason)
 
895
{
 
896
    debug("display start failed, sending <failed>\n");
 
897
    send_failed((struct sockaddr *)(d->from.data), d->from.length, d->name,
 
898
                d->sessionID, reason, d->xdmcpFd);
 
899
}
 
900
 
 
901
static void
 
902
send_refuse(struct sockaddr *from, int fromlen, CARD32 sessionID, int fd)
 
903
{
 
904
    XdmcpHeader header;
 
905
 
 
906
    debug("send <refuse> %ld\n", (long)sessionID);
 
907
    header.version = XDM_PROTOCOL_VERSION;
 
908
    header.opcode = (CARD16)REFUSE;
 
909
    header.length = 4;
 
910
    XdmcpWriteHeader(&buffer, &header);
 
911
    XdmcpWriteCARD32(&buffer, sessionID);
 
912
    XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
 
913
}
 
914
 
 
915
static void
 
916
manage(struct sockaddr *from, int fromlen, int length, int fd)
 
917
{
 
918
    CARD32 sessionID;
 
919
    CARD16 displayNumber;
 
920
    ARRAY8 displayClass;
 
921
    int expectlen;
 
922
    struct protoDisplay *pdpy;
 
923
    struct display *d;
 
924
    char *name = 0;
 
925
    char *class2 = 0;
 
926
    XdmcpNetaddr from_save;
 
927
    ARRAY8 clientAddress, clientPort;
 
928
    CARD16 connectionType;
 
929
 
 
930
    debug("<manage> %d\n", length);
 
931
    displayClass.data = 0;
 
932
    displayClass.length = 0;
 
933
    if (XdmcpReadCARD32(&buffer, &sessionID) &&
 
934
        XdmcpReadCARD16(&buffer, &displayNumber) &&
 
935
        XdmcpReadARRAY8(&buffer, &displayClass))
 
936
    {
 
937
        expectlen = 4 + /* session ID */
 
938
                    2 + /* displayNumber */
 
939
                    2 + displayClass.length; /* displayClass */
 
940
        if (expectlen != length) {
 
941
            debug("<manage> length error got %d expect %d\n", length, expectlen);
 
942
            goto abort;
 
943
        }
 
944
        pdpy = findProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber);
 
945
        debug("<manage> session ID %ld, pdpy %p\n", (long)sessionID, pdpy);
 
946
        if (!pdpy || pdpy->sessionID != sessionID) {
 
947
            /*
 
948
             * We may have already started a session for this display
 
949
             * but it hasn't seen the response in the form of an
 
950
             * XOpenDisplay() yet. So check if it is in the list of active
 
951
             * displays, and if so check that the session id's match.
 
952
             * If all this is true, then we have a duplicate request that
 
953
             * can be ignored.
 
954
             */
 
955
            if (!pdpy &&
 
956
                (d = findDisplayByAddress((XdmcpNetaddr)from, fromlen,
 
957
                                          displayNumber)) &&
 
958
                d->sessionID == sessionID)
 
959
            {
 
960
                debug("manage: got duplicate pkt, ignoring\n");
 
961
                goto abort;
 
962
            }
 
963
            debug("session ID %ld refused\n", (long)sessionID);
 
964
            if (pdpy)
 
965
                debug("existing session ID %ld\n", (long)pdpy->sessionID);
 
966
            send_refuse(from, fromlen, sessionID, fd);
 
967
        } else {
 
968
            name = networkAddressToName(pdpy->connectionType,
 
969
                                        &pdpy->connectionAddress,
 
970
                                        from,
 
971
                                        pdpy->displayNumber);
 
972
            if (!name) {
 
973
                debug("could not compute display name\n");
 
974
                send_failed(from, fromlen, "(no name)", sessionID,
 
975
                            "out of memory", fd);
 
976
                goto abort;
 
977
            }
 
978
            debug("computed display name: %s\n", name);
 
979
            if ((d = findDisplayByName(name))) {
 
980
                debug("terminating active session for %s\n", d->name);
 
981
                stopDisplay(d);
 
982
            }
 
983
            if (displayClass.length) {
 
984
                if (!strNDup(&class2, (char *)displayClass.data,
 
985
                             displayClass.length))
 
986
                {
 
987
                    send_failed(from, fromlen, name, sessionID,
 
988
                                "out of memory", fd);
 
989
                    goto abort;
 
990
                }
 
991
            }
 
992
            if (!(from_save = Malloc(fromlen))) {
 
993
                send_failed(from, fromlen, name, sessionID,
 
994
                            "out of memory", fd);
 
995
                goto abort;
 
996
            }
 
997
            memmove(from_save, from, fromlen);
 
998
            if (!(d = newDisplay(name))) {
 
999
                free(from_save);
 
1000
                send_failed(from, fromlen, name, sessionID,
 
1001
                            "out of memory", fd);
 
1002
                goto abort;
 
1003
            }
 
1004
            d->class2 = class2;
 
1005
            class2 = 0;
 
1006
            d->displayType = dForeign | dTransient | dFromXDMCP;
 
1007
            d->sessionID = pdpy->sessionID;
 
1008
            d->from.data = (unsigned char *)from_save;
 
1009
            d->from.length = fromlen;
 
1010
            d->displayNumber = pdpy->displayNumber;
 
1011
            convertClientAddress(from,
 
1012
                                 &clientAddress, &clientPort, &connectionType);
 
1013
            d->useChooser = False;
 
1014
            d->xdmcpFd = fd;
 
1015
            if (checkIndirectChoice(&clientAddress, &clientPort, connectionType) &&
 
1016
                useChooser(&clientAddress, connectionType))
 
1017
            {
 
1018
                d->useChooser = True;
 
1019
                debug("use chooser for %s\n", d->name);
 
1020
            }
 
1021
            d->clientAddr = clientAddress;
 
1022
            d->clientPort = clientPort;
 
1023
            d->connectionType = connectionType;
 
1024
            if (pdpy->fileAuthorization) {
 
1025
                d->authorizations = Malloc(sizeof(Xauth *));
 
1026
                if (!d->authorizations) {
 
1027
                    removeDisplay(d);
 
1028
                    send_failed(from, fromlen, name, sessionID,
 
1029
                                "out of memory", fd);
 
1030
                    goto abort;
 
1031
                }
 
1032
                d->authorizations[0] = pdpy->fileAuthorization;
 
1033
                d->authNum = 1;
 
1034
                pdpy->fileAuthorization = 0;
 
1035
            }
 
1036
            disposeProtoDisplay(pdpy);
 
1037
        }
 
1038
    }
 
1039
abort:
 
1040
    XdmcpDisposeARRAY8(&displayClass);
 
1041
    free(name);
 
1042
    free(class2);
 
1043
}
 
1044
 
 
1045
static void
 
1046
send_alive(struct sockaddr *from, int fromlen, int length, int fd)
 
1047
{
 
1048
    CARD32 sessionID;
 
1049
    CARD16 displayNumber;
 
1050
    struct display *d;
 
1051
    XdmcpHeader header;
 
1052
    CARD8 sendRunning;
 
1053
    CARD32 sendSessionID;
 
1054
 
 
1055
    debug("send <alive>\n");
 
1056
    if (XdmcpReadCARD16(&buffer, &displayNumber) &&
 
1057
        XdmcpReadCARD32(&buffer, &sessionID))
 
1058
    {
 
1059
        if (length == 6) {
 
1060
            if (!(d = findDisplayBySessionID(sessionID)))
 
1061
                d = findDisplayByAddress((XdmcpNetaddr)from, fromlen,
 
1062
                                         displayNumber);
 
1063
            sendRunning = 0;
 
1064
            sendSessionID = 0;
 
1065
            if (d && d->status == running) {
 
1066
                if (d->sessionID == sessionID)
 
1067
                    sendRunning = 1;
 
1068
                sendSessionID = d->sessionID;
 
1069
            }
 
1070
            header.version = XDM_PROTOCOL_VERSION;
 
1071
            header.opcode = (CARD16)ALIVE;
 
1072
            header.length = 5;
 
1073
            debug("<alive>: %d %ld\n", sendRunning, (long)sendSessionID);
 
1074
            XdmcpWriteHeader(&buffer, &header);
 
1075
            XdmcpWriteCARD8(&buffer, sendRunning);
 
1076
            XdmcpWriteCARD32(&buffer, sendSessionID);
 
1077
            XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
 
1078
        }
 
1079
    }
 
1080
}
 
1081
 
 
1082
 
 
1083
void
 
1084
processRequestSocket(int fd)
 
1085
{
 
1086
    XdmcpHeader header;
 
1087
#if defined(IPv6) && defined(AF_INET6)
 
1088
    struct sockaddr_storage addr;
 
1089
#else
 
1090
    struct sockaddr addr;
 
1091
#endif
 
1092
    int addrlen = sizeof(addr);
 
1093
 
 
1094
    debug("processRequestSocket\n");
 
1095
    bzero(&addr, sizeof(addr));
 
1096
    if (!XdmcpFill(fd, &buffer, (XdmcpNetaddr)&addr, &addrlen)) {
 
1097
        debug("XdmcpFill failed\n");
 
1098
        return;
 
1099
    }
 
1100
    if (!XdmcpReadHeader(&buffer, &header)) {
 
1101
        debug("XdmcpReadHeader failed\n");
 
1102
        return;
 
1103
    }
 
1104
    if (header.version != XDM_PROTOCOL_VERSION) {
 
1105
        debug("XDMCP header version read was %d, expected %d\n",
 
1106
              header.version, XDM_PROTOCOL_VERSION);
 
1107
        return;
 
1108
    }
 
1109
    debug("header: %d %d %d\n", header.version, header.opcode, header.length);
 
1110
    switch (header.opcode) {
 
1111
    case BROADCAST_QUERY:
 
1112
        broadcast_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
 
1113
        break;
 
1114
    case QUERY:
 
1115
        query_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
 
1116
        break;
 
1117
    case INDIRECT_QUERY:
 
1118
        indirect_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
 
1119
        break;
 
1120
    case FORWARD_QUERY:
 
1121
        forward_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
 
1122
        break;
 
1123
    case REQUEST:
 
1124
        request_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
 
1125
        break;
 
1126
    case MANAGE:
 
1127
        manage((struct sockaddr *)&addr, addrlen, header.length, fd);
 
1128
        break;
 
1129
    case KEEPALIVE:
 
1130
        send_alive((struct sockaddr *)&addr, addrlen, header.length, fd);
 
1131
        break;
 
1132
    }
 
1133
}
 
1134