/*  Functions for handling RPC

    ©1999 Joseph Walton

    This software is distributed under the terms of the GNU General Public
    License; either version 2 of the License, or (at your option) any
    later version.
*/

#include "rpc.h"
#include <stdio.h>
#include <proto/exec.h>
#include <proto/socket.h>

int32 *getString(int32 *ptr, int32 *limit, char *buf, int bufchars)
{
        int numChars;
        if (!ptr || (ptr >= limit))
                return NULL;

        numChars = G_UINT(*ptr++);
        if ((INT32S(numChars) > (limit - ptr)) || (numChars >= bufchars))
        {
                return NULL;
        }

        CopyMem(ptr, buf, numChars);
        buf[numChars] = '\0';
        return ptr + INT32S(numChars);
}

int32 *readAuth(int32 *ptr, int32 *limit, struct authunix *auth)
{
        int flavor, length, numIds, i;

        if ((limit - ptr) < 2)
                return NULL;

        flavor = G_INT(*ptr++);
        length = G_UINT(*ptr++);

        switch (flavor) {
                case AUTH_SYS:
                        auth->isUnix = TRUE;
                        if ((limit - ptr) < 2)
                                return NULL;

                        ptr++; // Discard the stamp

                        ptr = getString(ptr, limit, auth->machineName,
                            AUTH_SYS_MACHINENAMELEN);
                        if (!ptr)
                                return NULL;

                        if ((limit - ptr) < 3) {
                                return NULL;
                        }

                        auth->uid = G_UINT(*ptr++);
                        auth->gid = G_UINT(*ptr++);
                        numIds = G_UINT(*ptr++);

                        if ((numIds > 16) || (numIds > (limit - ptr)))
                                return NULL;

                        for (i = 0 ; i < numIds ; i++) {
                                auth->gids[i] = G_UINT(*ptr++);
                        }
                        auth->numGids = numIds;
                        break;

                default:
                        auth->isUnix = FALSE;
                        ptr += INT32S(length);
                        if (ptr >= limit)
                                return NULL;
                        break;
        }

        return ptr;
}

// Uses 5 int32s
int32 *PrepareAcceptedHeader(int32 id, int32 *ptr)
{
        *ptr++ = P_UINT(id);
        *ptr++ = P_ENUM(REPLY);
        *ptr++ = P_ENUM(MSG_ACCEPTED);
        *ptr++ = P_ENUM(AUTH_NONE);
        *ptr++ = P_UINT(0);
        return ptr;
}
