1/*
2 * swapped requests
3 */
4/*
5
6Copyright 1990, 1991, 1998  The Open Group
7
8Permission to use, copy, modify, distribute, and sell this software and its
9documentation for any purpose is hereby granted without fee, provided that
10the above copyright notice appear in all copies and that both that
11copyright notice and this permission notice appear in supporting
12documentation.
13
14The above copyright notice and this permission notice shall be included in
15all copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of The Open Group shall not be
25used in advertising or otherwise to promote the sale, use or other dealings
26in this Software without prior written authorization from The Open Group.
27
28 * Copyright 1990, 1991 Network Computing Devices;
29 * Portions Copyright 1987 by Digital Equipment Corporation
30 *
31 * Permission to use, copy, modify, distribute, and sell this software and
32 * its documentation for any purpose is hereby granted without fee, provided
33 * that the above copyright notice appear in all copies and that both that
34 * copyright notice and this permission notice appear in supporting
35 * documentation, and that the names of Network Computing Devices, or Digital
36 * not be used in advertising or publicity pertaining to distribution
37 * of the software without specific, written prior permission.
38 *
39 * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
40 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
41 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
42 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
46 * THIS SOFTWARE.
47 */
48
49#include	"config.h"
50
51#include	<swapreq.h>
52
53#include	<X11/fonts/FSproto.h>
54#include	"clientstr.h"
55#include	"globals.h"
56#include	"dispatch.h"
57
58/* Size including padding to next 32-bit boundary */
59#define PAD_TO_32BIT(e)		(((e) + 3) & ~3)
60
61void
62SwapLongs(long *list, unsigned long count)
63{
64    int         n;
65    register char *longs = (char *)list;
66
67    while (count >= 8) {
68	swapl(longs + 0, n);
69	swapl(longs + 4, n);
70	swapl(longs + 8, n);
71	swapl(longs + 12, n);
72	swapl(longs + 16, n);
73	swapl(longs + 20, n);
74	swapl(longs + 24, n);
75	swapl(longs + 28, n);
76	longs += 32;
77	count -= 8;
78    }
79    if (count != 0) {
80	do {
81	    swapl(longs, n);
82	    longs += 4;
83	} while (--count != 0);
84    }
85}
86
87/* Byte swap a list of shorts */
88
89void
90SwapShorts(short *list, unsigned long count)
91{
92    register char *shorts = (char *)list;
93    register int n;
94
95    while (count >= 16) {
96	swaps(shorts + 0, n);
97	swaps(shorts + 2, n);
98	swaps(shorts + 4, n);
99	swaps(shorts + 6, n);
100	swaps(shorts + 8, n);
101	swaps(shorts + 10, n);
102	swaps(shorts + 12, n);
103	swaps(shorts + 14, n);
104	swaps(shorts + 16, n);
105	swaps(shorts + 18, n);
106	swaps(shorts + 20, n);
107	swaps(shorts + 22, n);
108	swaps(shorts + 24, n);
109	swaps(shorts + 26, n);
110	swaps(shorts + 28, n);
111	swaps(shorts + 30, n);
112	shorts += 32;
113	count -= 16;
114    }
115    if (count != 0) {
116	do {
117	    swaps(shorts, n);
118	    shorts += 2;
119	} while (--count != 0);
120    }
121}
122
123/*
124 * used for all requests that have nothing but 'length' swapped
125 */
126int
127SProcSimpleRequest(ClientPtr client)
128{
129    REQUEST(fsReq);
130    stuff->length = lswaps(stuff->length);
131    return ((*ProcVector[stuff->reqType]) (client));
132}
133
134/*
135 * used for all requests that have nothing but 'length' & a resource id swapped
136 */
137int
138SProcResourceRequest(ClientPtr client)
139{
140    REQUEST(fsResourceReq);
141    stuff->length = lswaps(stuff->length);
142    stuff->id = lswapl(stuff->id);
143    return ((*ProcVector[stuff->reqType]) (client));
144}
145
146static int
147swap_auth(ClientPtr client, pointer data, int num, int length)
148{
149    unsigned char *p;
150    unsigned char t;
151    CARD16      namelen,
152                datalen;
153    int         i;
154
155    if (num == 0) {	/* Nothing to swap */
156	return (FSSuccess);
157    }
158
159    /* The font service protocol spec states that the lengths should always
160     * be in the client's native byte order, and thus need swapping for a
161     * byte-swapped client - but set_font_authorizations() in the X server
162     * sample implementation has always filled them in in big-endian format,
163     * and xfs was swapping when running on a byte-swapped connection, and
164     * then assuming the result was big-endian.
165     *
166     * It also specifies padding each string out to the next 32-bit boundary,
167     * but again, set_font_authorizations() in the X server sample
168     * implementation has always failed to do so, but byte-pads the total
169     * length of data instead.
170     *
171     * This code determines if the individual string lengths add up to the
172     * correct total length when interpreted as generated by the traditional
173     * sample implementation, and if so, uses them that way, otherwise it
174     * will swap them, to make them big-endian, before passing on to the
175     * unswapped code that assumes that they are big-endian.
176     */
177
178    /* First determine if data matches the traditional sample
179       implementation format */
180    for (i = 0, p = data; i < num; i++) {
181	if ((p - (unsigned char *)data) > (length - 4))
182	    break;
183
184	namelen = (p[0] << 8) + p[1];
185	datalen = (p[2] << 8) + p[3];
186	p += 4 + namelen + datalen;
187    }
188    if ((i == num) && (PAD_TO_32BIT(p - (unsigned char *)data) == length))
189	return (FSSuccess);
190
191    /* Length didn't match, so we'll try swapping & padding */
192    for (i = 0, p = data; i < num; i++) {
193	if ((p - (unsigned char *)data) > (length - 4))
194	    break;
195
196	namelen = (p[1] << 8) + p[0];
197	t = p[0];
198	p[0] = p[1];
199	p[1] = t;
200	p += 2;
201
202	datalen = (p[1] << 8) + p[0];
203	t = p[0];
204	p[0] = p[1];
205	p[1] = t;
206	p += 2 + PAD_TO_32BIT(namelen) + PAD_TO_32BIT(datalen);
207    }
208    if ((i == num) && ((p - (unsigned char *)data) == length))
209	return (FSSuccess);
210
211    /* If length didn't match either way, we give up. */
212    SendErrToClient(client, FSBadLength, (pointer)&length);
213    return (FSBadLength);
214}
215
216int
217SProcCreateAC(ClientPtr client)
218{
219    int status;
220    int length;
221
222    REQUEST(fsCreateACReq);
223    stuff->length = lswaps(stuff->length);
224    stuff->acid = lswapl(stuff->acid);
225    length = (stuff->length << 2) - sizeof(fsCreateACReq);
226    status = swap_auth(client, (pointer) &stuff[1],
227		       stuff->num_auths, length);
228    if (status != FSSuccess)
229	return (status);
230    return ((*ProcVector[stuff->reqType]) (client));
231}
232
233int
234SProcSetResolution(ClientPtr client)
235{
236    REQUEST(fsSetResolutionReq);
237    stuff->length = lswaps(stuff->length);
238    stuff->num_resolutions = lswaps(stuff->num_resolutions);
239    if ((int)stuff->length - (&stuff[1] - &stuff[0]) !=
240	stuff->num_resolutions * sizeof(fsResolution))
241	return (FSBadLength);
242    SwapShorts((short *) &stuff[1], stuff->num_resolutions);
243
244    return ((*ProcVector[stuff->reqType]) (client));
245}
246
247
248int
249SProcQueryExtension(ClientPtr client)
250{
251    REQUEST(fsQueryExtensionReq);
252    stuff->length = lswaps(stuff->length);
253    return ((*ProcVector[FS_QueryExtension]) (client));
254}
255
256int
257SProcListCatalogues(ClientPtr client)
258{
259    REQUEST(fsListCataloguesReq);
260    stuff->length = lswaps(stuff->length);
261    stuff->maxNames = lswapl(stuff->maxNames);
262    stuff->nbytes = lswaps(stuff->nbytes);
263    return ((*ProcVector[FS_ListCatalogues]) (client));
264}
265
266int
267SProcListFonts(ClientPtr client)
268{
269    REQUEST(fsListFontsReq);
270    stuff->length = lswaps(stuff->length);
271    stuff->maxNames = lswapl(stuff->maxNames);
272    stuff->nbytes = lswaps(stuff->nbytes);
273    return ((*ProcVector[FS_ListFonts]) (client));
274}
275
276int
277SProcListFontsWithXInfo(ClientPtr client)
278{
279    REQUEST(fsListFontsWithXInfoReq);
280    stuff->length = lswaps(stuff->length);
281    stuff->maxNames = lswapl(stuff->maxNames);
282    stuff->nbytes = lswaps(stuff->nbytes);
283    return ((*ProcVector[FS_ListFontsWithXInfo]) (client));
284}
285
286int
287SProcOpenBitmapFont(ClientPtr client)
288{
289    REQUEST(fsOpenBitmapFontReq);
290    stuff->length = lswaps(stuff->length);
291    stuff->fid = lswapl(stuff->fid);
292    stuff->format_hint = lswapl(stuff->format_hint);
293    stuff->format_mask = lswapl(stuff->format_mask);
294    return ((*ProcVector[FS_OpenBitmapFont]) (client));
295}
296
297int
298SProcQueryXExtents(ClientPtr client)
299{
300    REQUEST(fsQueryXExtents8Req); /* 8 and 16 are the same here */
301    stuff->length = lswaps(stuff->length);
302    stuff->fid = lswapl(stuff->fid);
303    stuff->num_ranges = lswapl(stuff->num_ranges);
304
305    return ((*ProcVector[stuff->reqType]) (client));
306}
307
308int
309SProcQueryXBitmaps(ClientPtr client)
310{
311    REQUEST(fsQueryXBitmaps8Req); /* 8 and 16 are the same here */
312    stuff->length = lswaps(stuff->length);
313    stuff->fid = lswapl(stuff->fid);
314    stuff->format = lswapl(stuff->format);
315    stuff->num_ranges = lswapl(stuff->num_ranges);
316
317    return ((*ProcVector[stuff->reqType]) (client));
318}
319
320int
321SwapConnClientPrefix(ClientPtr client, fsConnClientPrefix *pCCP)
322{
323#if 0
324    REQUEST(fsFakeReq);
325#endif
326
327    pCCP->major_version = lswaps(pCCP->major_version);
328    pCCP->minor_version = lswaps(pCCP->minor_version);
329    pCCP->auth_len = lswaps(pCCP->auth_len);
330    return (swap_auth(client, (pointer) &pCCP[1],
331		      pCCP->num_auths, pCCP->auth_len));
332}
333