/* Copyright (c) 1995-1999 NEC USA, Inc.  All rights reserved.               */
/*                                                                           */
/* The redistribution, use and modification in source or binary forms of     */
/* this software is subject to the conditions set forth in the copyright     */
/* document ("Copyright") included with this distribution.                   */

/*
 * $Id: socks5api.h,v 1.25.4.5 1999/02/03 22:34:54 steve Exp $
 */

#ifndef __SOCKS5API_H_
#define __SOCKS5API_H_

#ifndef P
#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
#endif
#endif

#define S5_SERVER_NUM    16
#define S5_ERRMSG_SIZE   128
#define S5_ENTRY_SIZE    128
#define S5_NAME_SIZE     64
#define S5_OPTION_SIZE  256
#define S5_APPNAME_SIZE  64
#define S5_USERNAME_SIZE 128
#define S5_HOSTNAME_SIZE 128
#define S5_FILENAME_SIZE 256
/*
#define S5_ENTRY_SIZE    256
#define S5_NAME_SIZE     256
#define S5_APPNAME_SIZE  256
#define S5_USERNAME_SIZE 256
#define S5_HOSTNAME_SIZE 256
#define S5_FILENAME_SIZE 1024
*/

#define S5InvalidIOHandle -1
typedef int S5IOHandle;

struct sockaddr_name {
    unsigned short sn_family;
    unsigned short sn_port;
    char sn_name[255];
};

#define AF_S5NAME 0xff

union tagS5NetAddr {
    struct sockaddr      sa;
    struct sockaddr_in   sin;
    struct sockaddr_name sn;
#ifdef HAVE_NETINET6_IN6_H
    struct sockaddr_in6  sin6;
#endif
};

typedef union tagS5NetAddr S5NetAddr;

struct tagS5Packet {
    char *data;
    int len, off;
    int oob;
};

typedef struct tagS5Packet S5Packet;

struct tagS5AuthInfo {
    void *context;
    int (*encode) P((S5Packet *, S5Packet *, int, void *));
    int (*check)  P((S5Packet *, void *));
    int (*clean)  P((void *));
};

typedef struct tagS5AuthInfo S5AuthInfo;

struct tagS5IOInfo {
    S5Packet ibuf, obuf;
    S5AuthInfo auth;
    S5IOHandle fd;
};

typedef struct tagS5IOInfo S5IOInfo;

struct tagS5LinkInfo {
    char srcName[S5_HOSTNAME_SIZE];
    char dstName[S5_HOSTNAME_SIZE];
    char retName[S5_HOSTNAME_SIZE];
    char sckName[S5_HOSTNAME_SIZE];
    char srcUser[S5_USERNAME_SIZE];
#ifdef USERPROXYFIX
    char logUser[S5_USERNAME_SIZE];
#define S5RESV_USERNAMEPROXY_BIT 0
#endif
    char dstServ[S5_APPNAME_SIZE];

    unsigned char nextVersion;
    unsigned char peerVersion;
    unsigned char peerCommand;
    unsigned char nextReserved;
    unsigned char peerReserved;
    unsigned char peerFlags;
    unsigned char peerAuth;

    u_short clientPort;
    
    S5NetAddr srcAddr; /* source address                                    */
    S5NetAddr dstAddr; /* destination address                               */
    S5NetAddr retAddr; /* returned or real destination address              */
    S5NetAddr bndAddr; /* source connection's inteface                      */
    S5NetAddr intAddr; /* destination connection's interface                */
    S5NetAddr sckAddr; /* Next step on the chain...                         */

    int inbc;          /* How many bytes have come in on this link          */
    int outbc;         /* How many bytes have gone out on this link         */

    S5NetAddr altSckAddrs[S5_SERVER_NUM]; /* Alternative next steps in the chain...       */
    int nAltSckAddrs;                     /* # of Alternative next steps in the chain...  */
};

typedef struct tagS5LinkInfo S5LinkInfo;

struct tagS5CommandInfo{
    void *option;
    int (*sendpkt) P((S5Packet *, S5LinkInfo *, void *, int *));
    int (*recvpkt) P((S5Packet *, S5LinkInfo *, void *, int *));
    int (*clean)   P((S5LinkInfo *, void *));
};

typedef struct tagS5CommandInfo S5CommandInfo;

struct tagS5FilterInfo { 
    void *option; 
    int (*filter) P((S5Packet *, S5Packet *, S5LinkInfo *, void *,int *, int *)); 
    int (*clean)  P((void *)); 
};

typedef struct tagS5FilterInfo S5FilterInfo;  


#define S5_DIRECTION_IN      1
#define S5_DIRECTION_OUT     2
#define S5_DIRECTION_ANY     3

#define S5_ACTION_READ       1
#define S5_ACTION_MORE_READ  2
#define S5_ACTION_WRITE      3
#define S5_ACTION_MORE_WRITE 4
#define S5_ACTION_CLOSE      5

#define S5_AUTH_CLIENT       1
#define S5_AUTH_SERVER       2
#define S5_AUTH_BOTH         3

#define S5_ENCODE            0
#define S5_DECODE            1

#define S5_SOCKS4      SOCKS4_VERSION
#define S5_SOCKS5      SOCKS5_VERSION

#ifdef FOR_CLIENT
#define APIPREFIX(x) S5C ## x
#else
#define APIPREFIX(x) S5S ## x
#endif

#define CLOSESOCKET            REAL(close)
#define RECVSOCKET(f, b, l, o) ((o)?REAL(recv)(f, b, l, o):REAL(read)(f, b, l))
#define SENDSOCKET(f, b, l, o) ((o)?REAL(send)(f, b, l, o):REAL(write)(f, b, l))
#define IOCTLSOCKET            ioctl
#define READFILE               REAL(read)
#define WRITEFILE              REAL(write)

#define SOCKETERROR(x)         x
#define GETERRNO()             errno
#define SETERRNO(x)            (errno =  (x))
#define SETSOCKETERROR(x)      (errno =  (x))
#define ISSOCKETERROR(x)       (errno == (x))

#endif
