/*
   cipelib - library routines common to CIPE (user-mode part) and PKCIPE

   Copyright 2000 Olaf Titz <olaf@bigred.inka.de>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version
   2 of the License, or (at your option) any later version.
*/
/* $Id: cipelib.h,v 1.9 2000/12/30 23:02:08 olaf Exp $ */

#ifndef _CIPELIB_H_
#define _CIPELIB_H_

#include <signal.h>
#include <stdarg.h>
#include <syslog.h>
#include <sys/uio.h>
#include <netinet/in.h>

#ifdef __GNUC__
#define INLINE static __inline__
#else
#define INLINE static
#ifndef __attribute__
#define __attribute__(x)
#endif
#endif

#ifdef __cplusplus
extern "C" {
#endif

/* Look up an address or address:port specification given in "c".
   Handles numeric and named addresses and services.
   "prot" is protocol name (like "tcp") or NULL for pure IP address.
   Result is in "sa".
   Returns 0 if successful, -1 if not.
*/
extern int getaddr(const char *c, struct sockaddr_in *sa, const char *prot);

/* Parse a line like "name=value" or "name value".
   Return the name in "n", the value in "v" as pointers into "b".
   The input buffer is changed!
*/
extern void parseopt(char *b, char **n, char **v);

/* Return a dynamically allocated sprintf'd string. */
extern char *dsprintf(const char *fmt, ...)
    __attribute__((format(printf,1,2)));

/* Standard signal handler: just sets "gotsig" to the signal number. */
extern sig_atomic_t gotsig;
extern void sighand(int s);

/* Replacement for signal(2) doing the right thing. */
extern void setsig(int sig, void (*fun)(int));

/* Return a string (static buffer) describing the result for a result code
   "r" (as of wait(2)).
*/
extern char *retstatus(int r);

/* If nonzero, cipe_[v]syslog goes to stderr instead of syslog */
extern int logstderr;

/* [v]syslog replacements. If level==LOG_STDERR always use stderr */

#define LOG_STDERR -1

extern void cipe_vsyslog(int level, const char *fmt, va_list v)
    __attribute__((format(printf,2,0)));

extern void cipe_syslog(int level, const char *fmt, ...)
    __attribute__((format(printf,2,3)));

#define Log cipe_syslog

#if defined(DEBUG) || defined(LIBRARY)

/* Debug level (bit mask, application specific) */
extern int debugging;

/* Do cipe_syslog(LOG_DEBUG, fmt, ...) if "level" is set in "debugging" */
extern void logdebug(int level, const char *fmt, ...)
    __attribute__((format(printf,2,3)));

#endif

#ifdef DEBUG
#define debug(x) logdebug x
#else
#define debug(x) /* nop */
#endif

/* Decode a hex string from "c" to "d", where d is "max" bytes long.
   Ignore non-hex characters in the input. Return actual decoded length.
*/
extern int gethex(const char *c, unsigned char *d, int max);

/* Hex-dump "len" bytes starting at "bp" to LOG_DEBUG. */
extern void hexdump(const unsigned char *bp, unsigned int len);

/* Return string (static buffer) containing hex code (w/o spaces)
   for "l" bytes starting at "d".
*/
extern char *hexstr(const void *d, int l);

/* Check file "f" and path up to it for wrong permissions. Note: this
   is only a first-order admin stupidity test, not attack-proofing.
   "fmask gives the bits which must not be set in the file mode,
   "dmask" the respective bits in the directory path.
   If "v"==0 don't complain if file does not exist.
*/
extern int secchk(const char *f, int fmask, int dmask, int v);

/* read(2) which guarantees to process all "len" bytes. */
extern int xread(int fd, void *d, size_t len);

/* write(2) which guarantees to process all "len" bytes. */
extern int xwrite(int fd, const void *d, size_t len);

/* writev(2) which guarantees to process all bytes.
   We need this because TCP does not guarantee atomicity.
   NOTE: "vec" is modified.
*/
extern int xwritev(int fd, struct iovec *vec, size_t cnt);

/* SOCKS5 errlist */
extern const char * const socks_errlist[];
#define SOCKS5_MAXERR 8

/* Open connection to SOCKS5 server */
extern int socks5_open(struct sockaddr_in *so);

/* Send SOCKS5 command. "so" is in-out parameter */
#define S5_CONN		1
#define S5_BIND		2
#define S5_UDP		3
extern int socks5_cmd(int fd, int cmd, struct sockaddr_in *so);

#ifdef __cplusplus
}
#endif

#endif
