Removed #ifdef __cplusplus from networking headers. The check is already done in cdefs.h (__BEGIN_DECLS) which I committed yesterday.
Committed libnetwork.so. I actually wanted to port BSD's libc/net resolver, but that one uses too many unsupported functions, so I basically merged libbind.so and libsocket.so into one library. Moved the libbind.so sources to libnetwork/dns. Cleaned up native part of libbind.so a little bit more. Though, the ugly hack remains. We nbetter pthread/mutex support. Added TODO that we also shousctl() into the kernel and libroot.so. Improved DEVNOTES a little bit. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15605 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -67,10 +67,6 @@
|
||||
#include <sys/bitypes.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define inet_addr __inet_addr
|
||||
#define inet_aton __inet_aton
|
||||
#define inet_lnaof __inet_lnaof
|
||||
@@ -107,8 +103,4 @@ u_int inet_nsap_addr __P((const char *, u_char *, int));
|
||||
char *inet_nsap_ntoa __P((int, const u_char *, char *));
|
||||
__END_DECLS
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_INET_H_ */
|
||||
|
||||
@@ -61,10 +61,6 @@
|
||||
#include <sys/bitypes.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Revision information. This is the release date in YYYYMMDD format.
|
||||
* It can change every day so the right thing to do with it is use it
|
||||
@@ -569,10 +565,6 @@ int ns_makecanon __P((const char *, char *, size_t));
|
||||
int ns_samename __P((const char *, const char *));
|
||||
__END_DECLS
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BIND_4_COMPAT
|
||||
#include <arpa/nameser_compat.h>
|
||||
#endif
|
||||
|
||||
@@ -99,10 +99,6 @@
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_HEQUIV
|
||||
#define _PATH_HEQUIV "/etc/hosts.equiv"
|
||||
#endif
|
||||
@@ -314,8 +310,4 @@ void setservent_r __P((int));
|
||||
void endservent_r __P((void));
|
||||
__END_DECLS
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_NETDB_H_ */
|
||||
|
||||
@@ -63,10 +63,6 @@
|
||||
#include <stdio.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Revision information. This is the release date in YYYYMMDD format.
|
||||
* It can change every day so the right thing to do with it is use it
|
||||
@@ -478,8 +474,4 @@ int res_getservers __P((res_state,
|
||||
union res_sockaddr_union *, int));
|
||||
__END_DECLS
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_RESOLV_H_ */
|
||||
|
||||
@@ -5,3 +5,4 @@ Package haiku-networkingkit-cvs :
|
||||
;
|
||||
|
||||
SubInclude HAIKU_TOP src kits network compat ;
|
||||
SubInclude HAIKU_TOP src kits network libnetwork ;
|
||||
|
||||
@@ -1,49 +1,9 @@
|
||||
BIND 9.3.1
|
||||
ported to Haiku
|
||||
See libnetwork/dns/DEVNOTES for general notes. This file contains information about the legacy libbind.so.
|
||||
|
||||
This file contains important information for developers who want to update this BIND port.
|
||||
I created config.h, port_before.h, and port_after.h with "configure --enable-threads --disable-ipv6" on a BONE-compatible system and fixed some mistakes that the script made. All changes to these three files are marked with a comment containing the keyword CHANGED.
|
||||
This folder and the headers folder contained within override the respective libnetwork/dns folder. Additionally, the legacy headers override the default posix headers.
|
||||
|
||||
Added folders and files:
|
||||
headers (some headers are not defined in Haiku)
|
||||
src (functions that are not part of Haiku, e.g.: strsep)
|
||||
The src folder is imported for sources. Currently, it is empty.
|
||||
|
||||
All BIND headers were moved to legacy/network (public) and private/net (private) in the system-wide headers folder.
|
||||
You may import files from Haiku's libroot.so if funtionality is missing.
|
||||
|
||||
Removed files:
|
||||
irs/
|
||||
dns_gr.c
|
||||
dns_pw.c
|
||||
gen_gr.c
|
||||
gen_pw.c
|
||||
getgrent.c
|
||||
getgrent_r.c
|
||||
getpwent.c
|
||||
getpwent_r.c
|
||||
irp_gr.c
|
||||
irp_pw.c
|
||||
lcl_gr.c
|
||||
lcl_pw.c
|
||||
nis_gr.c
|
||||
nis_ho.c
|
||||
nis_ng.c
|
||||
nis_nw.c
|
||||
nis_pr.c
|
||||
nis_pw.c
|
||||
nis_sv.c
|
||||
|
||||
|
||||
Porting issues:
|
||||
BIND wants to include sys/un.h and utmp.h. We do not have these, so I put empty headers into the private headers folder.
|
||||
|
||||
Added a hacky workaround when building for non-Haiku targets: select.h (in legacy headers) only declares pselect() for Haiku.
|
||||
|
||||
Added sources for compatibility:
|
||||
src/res_resultcodes.c: BONE's host command wants _res_resultcodes to be defined
|
||||
|
||||
Changes made to the sources and headers:
|
||||
nameser_compat.h: added check for __HAIKU__ and __BEOS__ to not redefine endianness
|
||||
|
||||
arpa/inet.h, netdb.h, resolv.h, nameser.h, nameser_compat.h: added check for __cplusplus, removed check for _REENTRANT (we are always reentrant), removed all checks for other operating systems
|
||||
|
||||
irs/gai_strerror.c, irs/irs_data.c: Switched to BeOS-native TLS in gai_strerror() and net_data_init() using a very ugly hack (see src/TLSInit.cpp). We need full mutex support!
|
||||
libbind.so links against libnet.so because it needs gethostname() on non-Haiku targets.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,154 +0,0 @@
|
||||
#ifndef DST_INTERNAL_H
|
||||
#define DST_INTERNAL_H
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include <sys/param.h>
|
||||
#if (!defined(BSD)) || (BSD < 199306)
|
||||
# include <sys/bitypes.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# ifdef POSIX_PATH_MAX
|
||||
# define PATH_MAX POSIX_PATH_MAX
|
||||
# else
|
||||
# define PATH_MAX 255 /* this is the value of POSIX_PATH_MAX */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct dst_key {
|
||||
char *dk_key_name; /* name of the key */
|
||||
int dk_key_size; /* this is the size of the key in bits */
|
||||
int dk_proto; /* what protocols this key can be used for */
|
||||
int dk_alg; /* algorithm number from key record */
|
||||
u_int32_t dk_flags; /* and the flags of the public key */
|
||||
u_int16_t dk_id; /* identifier of the key */
|
||||
void *dk_KEY_struct; /* pointer to key in crypto pkg fmt */
|
||||
struct dst_func *dk_func; /* point to cryptto pgk specific function table */
|
||||
} DST_KEY;
|
||||
#define HAS_DST_KEY
|
||||
|
||||
#include <isc/dst.h>
|
||||
/*
|
||||
* define what crypto systems are supported for RSA,
|
||||
* BSAFE is prefered over RSAREF; only one can be set at any time
|
||||
*/
|
||||
#if defined(BSAFE) && defined(RSAREF)
|
||||
# error "Cannot have both BSAFE and RSAREF defined"
|
||||
#endif
|
||||
|
||||
/* Declare dst_lib specific constants */
|
||||
#define KEY_FILE_FORMAT "1.2"
|
||||
|
||||
/* suffixes for key file names */
|
||||
#define PRIVATE_KEY "private"
|
||||
#define PUBLIC_KEY "key"
|
||||
|
||||
/* error handling */
|
||||
#ifdef REPORT_ERRORS
|
||||
#define EREPORT(str) printf str
|
||||
#else
|
||||
#define EREPORT(str) (void)0
|
||||
#endif
|
||||
|
||||
/* use our own special macro to FRRE memory */
|
||||
|
||||
#ifndef SAFE_FREE
|
||||
#define SAFE_FREE(a) \
|
||||
do{if(a != NULL){memset(a,0, sizeof(*a)); free(a); a=NULL;}} while (0)
|
||||
#define SAFE_FREE2(a,s) if (a != NULL && (long)s > 0){memset(a,0, s);free(a); a=NULL;}
|
||||
#endif
|
||||
|
||||
typedef struct dst_func {
|
||||
int (*sign)(const int mode, DST_KEY *key, void **context,
|
||||
const u_int8_t *data, const int len,
|
||||
u_int8_t *signature, const int sig_len);
|
||||
int (*verify)(const int mode, DST_KEY *key, void **context,
|
||||
const u_int8_t *data, const int len,
|
||||
const u_int8_t *signature, const int sig_len);
|
||||
int (*compare)(const DST_KEY *key1, const DST_KEY *key2);
|
||||
int (*generate)(DST_KEY *key, int parms);
|
||||
void *(*destroy)(void *key);
|
||||
/* conversion functions */
|
||||
int (*to_dns_key)(const DST_KEY *key, u_int8_t *out,
|
||||
const int out_len);
|
||||
int (*from_dns_key)(DST_KEY *key, const u_int8_t *str,
|
||||
const int str_len);
|
||||
int (*to_file_fmt)(const DST_KEY *key, char *out,
|
||||
const int out_len);
|
||||
int (*from_file_fmt)(DST_KEY *key, const char *out,
|
||||
const int out_len);
|
||||
|
||||
} dst_func;
|
||||
|
||||
extern dst_func *dst_t_func[DST_MAX_ALGS];
|
||||
extern const char *key_file_fmt_str;
|
||||
extern const char *dst_path;
|
||||
|
||||
#ifndef DST_HASH_SIZE
|
||||
#define DST_HASH_SIZE 20 /* RIPEMD160 and SHA-1 are 20 bytes MD5 is 16 */
|
||||
#endif
|
||||
|
||||
int dst_bsafe_init(void);
|
||||
|
||||
int dst_rsaref_init(void);
|
||||
|
||||
int dst_hmac_md5_init(void);
|
||||
|
||||
int dst_cylink_init(void);
|
||||
|
||||
int dst_eay_dss_init(void);
|
||||
|
||||
/* from higher level support routines */
|
||||
int dst_s_calculate_bits( const u_int8_t *str, const int max_bits);
|
||||
int dst_s_verify_str( const char **buf, const char *str);
|
||||
|
||||
|
||||
/* conversion between dns names and key file names */
|
||||
size_t dst_s_filename_length( const char *name, const char *suffix);
|
||||
int dst_s_build_filename( char *filename, const char *name,
|
||||
u_int16_t id, int alg, const char *suffix,
|
||||
size_t filename_length);
|
||||
|
||||
FILE *dst_s_fopen (const char *filename, const char *mode, int perm);
|
||||
|
||||
/*
|
||||
* read and write network byte order into u_int?_t
|
||||
* all of these should be retired
|
||||
*/
|
||||
u_int16_t dst_s_get_int16( const u_int8_t *buf);
|
||||
void dst_s_put_int16( u_int8_t *buf, const u_int16_t val);
|
||||
|
||||
u_int32_t dst_s_get_int32( const u_int8_t *buf);
|
||||
void dst_s_put_int32( u_int8_t *buf, const u_int32_t val);
|
||||
|
||||
#ifdef DUMP
|
||||
# undef DUMP
|
||||
# define DUMP(a,b,c,d) dst_s_dump(a,b,c,d)
|
||||
#else
|
||||
# define DUMP(a,b,c,d)
|
||||
#endif
|
||||
void
|
||||
dst_s_dump(const int mode, const u_char *data, const int size,
|
||||
const char *msg);
|
||||
|
||||
|
||||
|
||||
#endif /* DST_INTERNAL_H */
|
||||
@@ -1,468 +0,0 @@
|
||||
#ifdef HMAC_MD5
|
||||
#ifndef LINT
|
||||
static const char rcsid[] = "$Header: /proj/cvs/prod/bind9/lib/bind/dst/hmac_link.c,v 1.2.2.1 2003/06/27 03:51:36 marka Exp $";
|
||||
#endif
|
||||
/*
|
||||
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains an implementation of the HMAC-MD5 algorithm.
|
||||
*/
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
#ifdef USE_MD5
|
||||
# include "md5.h"
|
||||
# ifndef _MD5_H_
|
||||
# define _MD5_H_ 1 /* make sure we do not include rsaref md5.h file */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
|
||||
#define HMAC_LEN 64
|
||||
#define HMAC_IPAD 0x36
|
||||
#define HMAC_OPAD 0x5c
|
||||
#define MD5_LEN 16
|
||||
|
||||
|
||||
typedef struct hmackey {
|
||||
u_char hk_ipad[64], hk_opad[64];
|
||||
} HMAC_Key;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_hmac_md5_sign
|
||||
* Call HMAC signing functions to sign a block of data.
|
||||
* There are three steps to signing, INIT (initialize structures),
|
||||
* UPDATE (hash (more) data), FINAL (generate a signature). This
|
||||
* routine performs one or more of these steps.
|
||||
* Parameters
|
||||
* mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
|
||||
* priv_key key to use for signing.
|
||||
* context the context to be used in this digest
|
||||
* data data to be signed.
|
||||
* len length in bytes of data.
|
||||
* signature location to store signature.
|
||||
* sig_len size of the signature location
|
||||
* returns
|
||||
* N Success on SIG_MODE_FINAL = returns signature length in bytes
|
||||
* 0 Success on SIG_MODE_INIT and UPDATE
|
||||
* <0 Failure
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context,
|
||||
const u_char *data, const int len,
|
||||
u_char *signature, const int sig_len)
|
||||
{
|
||||
HMAC_Key *key;
|
||||
int sign_len = 0;
|
||||
MD5_CTX *ctx = NULL;
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
ctx = (MD5_CTX *) malloc(sizeof(*ctx));
|
||||
else if (context)
|
||||
ctx = (MD5_CTX *) *context;
|
||||
if (ctx == NULL)
|
||||
return (-1);
|
||||
|
||||
if (d_key == NULL || d_key->dk_KEY_struct == NULL)
|
||||
return (-1);
|
||||
key = (HMAC_Key *) d_key->dk_KEY_struct;
|
||||
|
||||
if (mode & SIG_MODE_INIT) {
|
||||
MD5Init(ctx);
|
||||
MD5Update(ctx, key->hk_ipad, HMAC_LEN);
|
||||
}
|
||||
|
||||
if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
|
||||
MD5Update(ctx, data, len);
|
||||
|
||||
if (mode & SIG_MODE_FINAL) {
|
||||
if (signature == NULL || sig_len < MD5_LEN)
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
MD5Final(signature, ctx);
|
||||
|
||||
/* perform outer MD5 */
|
||||
MD5Init(ctx);
|
||||
MD5Update(ctx, key->hk_opad, HMAC_LEN);
|
||||
MD5Update(ctx, signature, MD5_LEN);
|
||||
MD5Final(signature, ctx);
|
||||
sign_len = MD5_LEN;
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
else {
|
||||
if (context == NULL)
|
||||
return (-1);
|
||||
*context = (void *) ctx;
|
||||
}
|
||||
return (sign_len);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_hmac_md5_verify()
|
||||
* Calls HMAC verification routines. There are three steps to
|
||||
* verification, INIT (initialize structures), UPDATE (hash (more) data),
|
||||
* FINAL (generate a signature). This routine performs one or more of
|
||||
* these steps.
|
||||
* Parameters
|
||||
* mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
|
||||
* dkey key to use for verify.
|
||||
* data data signed.
|
||||
* len length in bytes of data.
|
||||
* signature signature.
|
||||
* sig_len length in bytes of signature.
|
||||
* returns
|
||||
* 0 Success
|
||||
* <0 Failure
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context,
|
||||
const u_char *data, const int len,
|
||||
const u_char *signature, const int sig_len)
|
||||
{
|
||||
HMAC_Key *key;
|
||||
MD5_CTX *ctx = NULL;
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
ctx = (MD5_CTX *) malloc(sizeof(*ctx));
|
||||
else if (context)
|
||||
ctx = (MD5_CTX *) *context;
|
||||
if (ctx == NULL)
|
||||
return (-1);
|
||||
|
||||
if (d_key == NULL || d_key->dk_KEY_struct == NULL)
|
||||
return (-1);
|
||||
|
||||
key = (HMAC_Key *) d_key->dk_KEY_struct;
|
||||
if (mode & SIG_MODE_INIT) {
|
||||
MD5Init(ctx);
|
||||
MD5Update(ctx, key->hk_ipad, HMAC_LEN);
|
||||
}
|
||||
if ((mode & SIG_MODE_UPDATE) && (data && len > 0))
|
||||
MD5Update(ctx, data, len);
|
||||
|
||||
if (mode & SIG_MODE_FINAL) {
|
||||
u_char digest[MD5_LEN];
|
||||
if (signature == NULL || key == NULL || sig_len != MD5_LEN)
|
||||
return (VERIFY_FINAL_FAILURE);
|
||||
MD5Final(digest, ctx);
|
||||
|
||||
/* perform outer MD5 */
|
||||
MD5Init(ctx);
|
||||
MD5Update(ctx, key->hk_opad, HMAC_LEN);
|
||||
MD5Update(ctx, digest, MD5_LEN);
|
||||
MD5Final(digest, ctx);
|
||||
|
||||
SAFE_FREE(ctx);
|
||||
if (memcmp(digest, signature, MD5_LEN) != 0)
|
||||
return (VERIFY_FINAL_FAILURE);
|
||||
}
|
||||
else {
|
||||
if (context == NULL)
|
||||
return (-1);
|
||||
*context = (void *) ctx;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_buffer_to_hmac_md5
|
||||
* Converts key from raw data to an HMAC Key
|
||||
* This function gets in a pointer to the data
|
||||
* Parameters
|
||||
* hkey the HMAC key to be filled in
|
||||
* key the key in raw format
|
||||
* keylen the length of the key
|
||||
* Return
|
||||
* 0 Success
|
||||
* <0 Failure
|
||||
*/
|
||||
static int
|
||||
dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const int keylen)
|
||||
{
|
||||
int i;
|
||||
HMAC_Key *hkey = NULL;
|
||||
MD5_CTX ctx;
|
||||
int local_keylen = keylen;
|
||||
|
||||
if (dkey == NULL || key == NULL || keylen < 0)
|
||||
return (-1);
|
||||
|
||||
if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL)
|
||||
return (-2);
|
||||
|
||||
memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad));
|
||||
memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad));
|
||||
|
||||
/* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */
|
||||
if (keylen > HMAC_LEN) {
|
||||
u_char tk[MD5_LEN];
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, key, keylen);
|
||||
MD5Final(tk, &ctx);
|
||||
memset((void *) &ctx, 0, sizeof(ctx));
|
||||
key = tk;
|
||||
local_keylen = MD5_LEN;
|
||||
}
|
||||
/* start out by storing key in pads */
|
||||
memcpy(hkey->hk_ipad, key, local_keylen);
|
||||
memcpy(hkey->hk_opad, key, local_keylen);
|
||||
|
||||
/* XOR key with hk_ipad and opad values */
|
||||
for (i = 0; i < HMAC_LEN; i++) {
|
||||
hkey->hk_ipad[i] ^= HMAC_IPAD;
|
||||
hkey->hk_opad[i] ^= HMAC_OPAD;
|
||||
}
|
||||
dkey->dk_key_size = local_keylen;
|
||||
dkey->dk_KEY_struct = (void *) hkey;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_hmac_md5_key_to_file_format
|
||||
* Encodes an HMAC Key into the portable file format.
|
||||
* Parameters
|
||||
* hkey HMAC KEY structure
|
||||
* buff output buffer
|
||||
* buff_len size of output buffer
|
||||
* Return
|
||||
* 0 Failure - null input hkey
|
||||
* -1 Failure - not enough space in output area
|
||||
* N Success - Length of data returned in buff
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff,
|
||||
const int buff_len)
|
||||
{
|
||||
char *bp;
|
||||
int len, b_len, i, key_len;
|
||||
u_char key[HMAC_LEN];
|
||||
HMAC_Key *hkey;
|
||||
|
||||
if (dkey == NULL || dkey->dk_KEY_struct == NULL)
|
||||
return (0);
|
||||
if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str))
|
||||
return (-1); /* no OR not enough space in output area */
|
||||
|
||||
hkey = (HMAC_Key *) dkey->dk_KEY_struct;
|
||||
memset(buff, 0, buff_len); /* just in case */
|
||||
/* write file header */
|
||||
sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
|
||||
memset(key, 0, HMAC_LEN);
|
||||
for (i = 0; i < HMAC_LEN; i++)
|
||||
key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
|
||||
for (i = HMAC_LEN - 1; i >= 0; i--)
|
||||
if (key[i] != 0)
|
||||
break;
|
||||
key_len = i + 1;
|
||||
|
||||
strcat(bp, "Key: ");
|
||||
bp += strlen("Key: ");
|
||||
b_len = buff_len - (bp - buff);
|
||||
|
||||
len = b64_ntop(key, key_len, bp, b_len);
|
||||
if (len < 0)
|
||||
return (-1);
|
||||
bp += len;
|
||||
*(bp++) = '\n';
|
||||
*bp = '\0';
|
||||
b_len = buff_len - (bp - buff);
|
||||
|
||||
return (buff_len - b_len);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_hmac_md5_key_from_file_format
|
||||
* Converts contents of a key file into an HMAC key.
|
||||
* Parameters
|
||||
* hkey structure to put key into
|
||||
* buff buffer containing the encoded key
|
||||
* buff_len the length of the buffer
|
||||
* Return
|
||||
* n >= 0 Foot print of the key converted
|
||||
* n < 0 Error in conversion
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff,
|
||||
const int buff_len)
|
||||
{
|
||||
const char *p = buff, *eol;
|
||||
u_char key[HMAC_LEN+1]; /* b64_pton needs more than 64 bytes do decode
|
||||
* it should probably be fixed rather than doing
|
||||
* this
|
||||
*/
|
||||
u_char *tmp;
|
||||
int key_len, len;
|
||||
|
||||
if (dkey == NULL)
|
||||
return (-2);
|
||||
if (buff == NULL || buff_len < 0)
|
||||
return (-1);
|
||||
|
||||
memset(key, 0, sizeof(key));
|
||||
|
||||
if (!dst_s_verify_str(&p, "Key: "))
|
||||
return (-3);
|
||||
|
||||
eol = strchr(p, '\n');
|
||||
if (eol == NULL)
|
||||
return (-4);
|
||||
len = eol - p;
|
||||
tmp = malloc(len + 2);
|
||||
memcpy(tmp, p, len);
|
||||
*(tmp + len) = 0x0;
|
||||
key_len = b64_pton((char *)tmp, key, HMAC_LEN+1); /* see above */
|
||||
SAFE_FREE2(tmp, len + 2);
|
||||
|
||||
if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) {
|
||||
return (-6);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_hmac_md5_to_dns_key()
|
||||
* function to extract hmac key from DST_KEY structure
|
||||
* intput:
|
||||
* in_key: HMAC-MD5 key
|
||||
* output:
|
||||
* out_str: buffer to write ot
|
||||
* out_len: size of output buffer
|
||||
* returns:
|
||||
* number of bytes written to output buffer
|
||||
*/
|
||||
static int
|
||||
dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str,
|
||||
const int out_len)
|
||||
{
|
||||
|
||||
HMAC_Key *hkey;
|
||||
int i;
|
||||
|
||||
if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
|
||||
out_len <= in_key->dk_key_size || out_str == NULL)
|
||||
return (-1);
|
||||
|
||||
hkey = (HMAC_Key *) in_key->dk_KEY_struct;
|
||||
for (i = 0; i < in_key->dk_key_size; i++)
|
||||
out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD;
|
||||
return (i);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* dst_hmac_md5_compare_keys
|
||||
* Compare two keys for equality.
|
||||
* Return
|
||||
* 0 The keys are equal
|
||||
* NON-ZERO The keys are not equal
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
|
||||
{
|
||||
HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct;
|
||||
HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct;
|
||||
return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* dst_hmac_md5_free_key_structure
|
||||
* Frees all (none) dynamically allocated structures in hkey
|
||||
*/
|
||||
|
||||
static void *
|
||||
dst_hmac_md5_free_key_structure(void *key)
|
||||
{
|
||||
HMAC_Key *hkey = key;
|
||||
SAFE_FREE(hkey);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* dst_hmac_md5_generate_key
|
||||
* Creates a HMAC key of size size with a maximum size of 63 bytes
|
||||
* generating a HMAC key larger than 63 bytes makes no sense as that key
|
||||
* is digested before use.
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_hmac_md5_generate_key(DST_KEY *key, const int nothing)
|
||||
{
|
||||
(void)key;
|
||||
(void)nothing;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_hmac_md5_init() Function to answer set up function pointers for HMAC
|
||||
* related functions
|
||||
*/
|
||||
int
|
||||
dst_hmac_md5_init()
|
||||
{
|
||||
if (dst_t_func[KEY_HMAC_MD5] != NULL)
|
||||
return (1);
|
||||
dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func));
|
||||
if (dst_t_func[KEY_HMAC_MD5] == NULL)
|
||||
return (0);
|
||||
memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func));
|
||||
dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign;
|
||||
dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify;
|
||||
dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys;
|
||||
dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key;
|
||||
dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure;
|
||||
dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key;
|
||||
dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5;
|
||||
dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format;
|
||||
dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format;
|
||||
return (1);
|
||||
}
|
||||
|
||||
#else
|
||||
#define dst_hmac_md5_init __dst_hmac_md5_init
|
||||
|
||||
int
|
||||
dst_hmac_md5_init(){
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
@@ -1,101 +0,0 @@
|
||||
/* crypto/md/md5.h */
|
||||
/* Copyright (C) 1995-1997 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef HEADER_MD5_H
|
||||
#define HEADER_MD5_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MD5_CBLOCK 64
|
||||
#define MD5_LBLOCK 16
|
||||
#define MD5_BLOCK 16
|
||||
#define MD5_LAST_BLOCK 56
|
||||
#define MD5_LENGTH_BLOCK 8
|
||||
#define MD5_DIGEST_LENGTH 16
|
||||
|
||||
typedef struct MD5state_st
|
||||
{
|
||||
unsigned long A,B,C,D;
|
||||
unsigned long Nl,Nh;
|
||||
unsigned long data[MD5_LBLOCK];
|
||||
int num;
|
||||
} MD5_CTX;
|
||||
|
||||
#ifndef NOPROTO
|
||||
void MD5_Init(MD5_CTX *c);
|
||||
void MD5_Update(MD5_CTX *c, const unsigned char *data, unsigned long len);
|
||||
void MD5_Final(unsigned char *md, MD5_CTX *c);
|
||||
unsigned char *MD5(unsigned char *d, unsigned long n, unsigned char *md);
|
||||
#else
|
||||
void MD5_Init();
|
||||
void MD5_Update();
|
||||
void MD5_Final();
|
||||
unsigned char *MD5();
|
||||
#endif
|
||||
|
||||
/* to provide backward compatabilty to RSAREF calls [email protected] 1997/11/14 */
|
||||
#define MD5Init(c) MD5_Init(c)
|
||||
#define MD5Update(c,data, len) MD5_Update(c,data,len)
|
||||
#define MD5Final(md, c) MD5_Final(md, c)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,370 +0,0 @@
|
||||
/* crypto/md/md5_dgst.c */
|
||||
/* Copyright (C) 1995-1997 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifdef USE_MD5 /* Added by [email protected] 1998/1/26 */
|
||||
#include <port_before.h>
|
||||
#include <stdio.h>
|
||||
#include "md5_locl.h"
|
||||
#include <port_after.h>
|
||||
|
||||
const char *MD5_version="MD5 part of SSLeay 0.8.1 19-Jul-1997";
|
||||
|
||||
/* Implemented from RFC1321 The MD5 Message-Digest Algorithm
|
||||
*/
|
||||
|
||||
#define INIT_DATA_A (unsigned long)0x67452301L
|
||||
#define INIT_DATA_B (unsigned long)0xefcdab89L
|
||||
#define INIT_DATA_C (unsigned long)0x98badcfeL
|
||||
#define INIT_DATA_D (unsigned long)0x10325476L
|
||||
|
||||
#ifndef NOPROTO
|
||||
static void md5_block(MD5_CTX *c, unsigned long *p);
|
||||
#else
|
||||
static void md5_block();
|
||||
#endif
|
||||
|
||||
void MD5_Init(c)
|
||||
MD5_CTX *c;
|
||||
{
|
||||
c->A=INIT_DATA_A;
|
||||
c->B=INIT_DATA_B;
|
||||
c->C=INIT_DATA_C;
|
||||
c->D=INIT_DATA_D;
|
||||
c->Nl=0;
|
||||
c->Nh=0;
|
||||
c->num=0;
|
||||
}
|
||||
|
||||
void MD5_Update(c, data, len)
|
||||
MD5_CTX *c;
|
||||
register const unsigned char *data;
|
||||
unsigned long len;
|
||||
{
|
||||
register ULONG *p;
|
||||
int sw,sc;
|
||||
ULONG l;
|
||||
|
||||
if (len == 0U) return;
|
||||
|
||||
l=(c->Nl+(len<<3))&0xffffffffL;
|
||||
/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
|
||||
* Wei Dai <[email protected]> for pointing it out. */
|
||||
if (l < c->Nl) /* overflow */
|
||||
c->Nh++;
|
||||
c->Nh+=(len>>29);
|
||||
c->Nl=l;
|
||||
|
||||
if (c->num != 0)
|
||||
{
|
||||
p=c->data;
|
||||
sw=c->num>>2;
|
||||
sc=c->num&0x03;
|
||||
|
||||
if ((c->num+len) >= (size_t)MD5_CBLOCK)
|
||||
{
|
||||
l= p[sw];
|
||||
p_c2l(data,l,sc);
|
||||
p[sw++]=l;
|
||||
for (; sw<MD5_LBLOCK; sw++)
|
||||
{
|
||||
c2l(data,l);
|
||||
p[sw]=l;
|
||||
}
|
||||
len-=(MD5_CBLOCK-c->num);
|
||||
|
||||
md5_block(c,p);
|
||||
c->num=0;
|
||||
/* drop through and do the rest */
|
||||
}
|
||||
else
|
||||
{
|
||||
int ew,ec;
|
||||
|
||||
c->num+=(int)len;
|
||||
if ((sc+len) < 4U) /* ugly, add char's to a word */
|
||||
{
|
||||
l= p[sw];
|
||||
p_c2l_p(data,l,sc,len);
|
||||
p[sw]=l;
|
||||
}
|
||||
else
|
||||
{
|
||||
ew=(c->num>>2);
|
||||
ec=(c->num&0x03);
|
||||
l= p[sw];
|
||||
p_c2l(data,l,sc);
|
||||
p[sw++]=l;
|
||||
for (; sw < ew; sw++)
|
||||
{ c2l(data,l); p[sw]=l; }
|
||||
if (ec)
|
||||
{
|
||||
c2l_p(data,l,ec);
|
||||
p[sw]=l;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* we now can process the input data in blocks of MD5_CBLOCK
|
||||
* chars and save the leftovers to c->data. */
|
||||
p=c->data;
|
||||
while (len >= (size_t)MD5_CBLOCK)
|
||||
{
|
||||
#if defined(L_ENDIAN) || defined(B_ENDIAN)
|
||||
memcpy(p,data,MD5_CBLOCK);
|
||||
data+=MD5_CBLOCK;
|
||||
#ifdef B_ENDIAN
|
||||
for (sw=(MD5_LBLOCK/4); sw; sw--)
|
||||
{
|
||||
Endian_Reverse32(p[0]);
|
||||
Endian_Reverse32(p[1]);
|
||||
Endian_Reverse32(p[2]);
|
||||
Endian_Reverse32(p[3]);
|
||||
p+=4;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
for (sw=(MD5_LBLOCK/4); sw; sw--)
|
||||
{
|
||||
c2l(data,l); *(p++)=l;
|
||||
c2l(data,l); *(p++)=l;
|
||||
c2l(data,l); *(p++)=l;
|
||||
c2l(data,l); *(p++)=l;
|
||||
}
|
||||
#endif
|
||||
p=c->data;
|
||||
md5_block(c,p);
|
||||
len-=MD5_CBLOCK;
|
||||
}
|
||||
sc=(int)len;
|
||||
c->num=sc;
|
||||
if (sc)
|
||||
{
|
||||
sw=sc>>2; /* words to copy */
|
||||
#ifdef L_ENDIAN
|
||||
p[sw]=0;
|
||||
memcpy(p,data,sc);
|
||||
#else
|
||||
sc&=0x03;
|
||||
for ( ; sw; sw--)
|
||||
{ c2l(data,l); *(p++)=l; }
|
||||
c2l_p(data,l,sc);
|
||||
*p=l;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void md5_block(c, X)
|
||||
MD5_CTX *c;
|
||||
register ULONG *X;
|
||||
{
|
||||
register ULONG A,B,C,D;
|
||||
|
||||
A=c->A;
|
||||
B=c->B;
|
||||
C=c->C;
|
||||
D=c->D;
|
||||
|
||||
/* Round 0 */
|
||||
R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
|
||||
R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
|
||||
R0(C,D,A,B,X[ 2],17,0x242070dbL);
|
||||
R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
|
||||
R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
|
||||
R0(D,A,B,C,X[ 5],12,0x4787c62aL);
|
||||
R0(C,D,A,B,X[ 6],17,0xa8304613L);
|
||||
R0(B,C,D,A,X[ 7],22,0xfd469501L);
|
||||
R0(A,B,C,D,X[ 8], 7,0x698098d8L);
|
||||
R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
|
||||
R0(C,D,A,B,X[10],17,0xffff5bb1L);
|
||||
R0(B,C,D,A,X[11],22,0x895cd7beL);
|
||||
R0(A,B,C,D,X[12], 7,0x6b901122L);
|
||||
R0(D,A,B,C,X[13],12,0xfd987193L);
|
||||
R0(C,D,A,B,X[14],17,0xa679438eL);
|
||||
R0(B,C,D,A,X[15],22,0x49b40821L);
|
||||
/* Round 1 */
|
||||
R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
|
||||
R1(D,A,B,C,X[ 6], 9,0xc040b340L);
|
||||
R1(C,D,A,B,X[11],14,0x265e5a51L);
|
||||
R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
|
||||
R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
|
||||
R1(D,A,B,C,X[10], 9,0x02441453L);
|
||||
R1(C,D,A,B,X[15],14,0xd8a1e681L);
|
||||
R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
|
||||
R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
|
||||
R1(D,A,B,C,X[14], 9,0xc33707d6L);
|
||||
R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
|
||||
R1(B,C,D,A,X[ 8],20,0x455a14edL);
|
||||
R1(A,B,C,D,X[13], 5,0xa9e3e905L);
|
||||
R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
|
||||
R1(C,D,A,B,X[ 7],14,0x676f02d9L);
|
||||
R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
|
||||
/* Round 2 */
|
||||
R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
|
||||
R2(D,A,B,C,X[ 8],11,0x8771f681L);
|
||||
R2(C,D,A,B,X[11],16,0x6d9d6122L);
|
||||
R2(B,C,D,A,X[14],23,0xfde5380cL);
|
||||
R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
|
||||
R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
|
||||
R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
|
||||
R2(B,C,D,A,X[10],23,0xbebfbc70L);
|
||||
R2(A,B,C,D,X[13], 4,0x289b7ec6L);
|
||||
R2(D,A,B,C,X[ 0],11,0xeaa127faL);
|
||||
R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
|
||||
R2(B,C,D,A,X[ 6],23,0x04881d05L);
|
||||
R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
|
||||
R2(D,A,B,C,X[12],11,0xe6db99e5L);
|
||||
R2(C,D,A,B,X[15],16,0x1fa27cf8L);
|
||||
R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
|
||||
/* Round 3 */
|
||||
R3(A,B,C,D,X[ 0], 6,0xf4292244L);
|
||||
R3(D,A,B,C,X[ 7],10,0x432aff97L);
|
||||
R3(C,D,A,B,X[14],15,0xab9423a7L);
|
||||
R3(B,C,D,A,X[ 5],21,0xfc93a039L);
|
||||
R3(A,B,C,D,X[12], 6,0x655b59c3L);
|
||||
R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
|
||||
R3(C,D,A,B,X[10],15,0xffeff47dL);
|
||||
R3(B,C,D,A,X[ 1],21,0x85845dd1L);
|
||||
R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
|
||||
R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
|
||||
R3(C,D,A,B,X[ 6],15,0xa3014314L);
|
||||
R3(B,C,D,A,X[13],21,0x4e0811a1L);
|
||||
R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
|
||||
R3(D,A,B,C,X[11],10,0xbd3af235L);
|
||||
R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
|
||||
R3(B,C,D,A,X[ 9],21,0xeb86d391L);
|
||||
|
||||
c->A+=A&0xffffffffL;
|
||||
c->B+=B&0xffffffffL;
|
||||
c->C+=C&0xffffffffL;
|
||||
c->D+=D&0xffffffffL;
|
||||
}
|
||||
|
||||
void MD5_Final(md, c)
|
||||
unsigned char *md;
|
||||
MD5_CTX *c;
|
||||
{
|
||||
register int i,j;
|
||||
register ULONG l;
|
||||
register ULONG *p;
|
||||
static unsigned char end[4]={0x80,0x00,0x00,0x00};
|
||||
unsigned char *cp=end;
|
||||
|
||||
/* c->num should definitly have room for at least one more byte. */
|
||||
p=c->data;
|
||||
j=c->num;
|
||||
i=j>>2;
|
||||
|
||||
/* purify often complains about the following line as an
|
||||
* Uninitialized Memory Read. While this can be true, the
|
||||
* following p_c2l macro will reset l when that case is true.
|
||||
* This is because j&0x03 contains the number of 'valid' bytes
|
||||
* already in p[i]. If and only if j&0x03 == 0, the UMR will
|
||||
* occur but this is also the only time p_c2l will do
|
||||
* l= *(cp++) instead of l|= *(cp++)
|
||||
* Many thanks to Alex Tang <[email protected]> for pickup this
|
||||
* 'potential bug' */
|
||||
#ifdef PURIFY
|
||||
if ((j&0x03) == 0) p[i]=0;
|
||||
#endif
|
||||
l=p[i];
|
||||
p_c2l(cp,l,j&0x03);
|
||||
p[i]=l;
|
||||
i++;
|
||||
/* i is the next 'undefined word' */
|
||||
if (c->num >= MD5_LAST_BLOCK)
|
||||
{
|
||||
for (; i<MD5_LBLOCK; i++)
|
||||
p[i]=0;
|
||||
md5_block(c,p);
|
||||
i=0;
|
||||
}
|
||||
for (; i<(MD5_LBLOCK-2); i++)
|
||||
p[i]=0;
|
||||
p[MD5_LBLOCK-2]=c->Nl;
|
||||
p[MD5_LBLOCK-1]=c->Nh;
|
||||
md5_block(c,p);
|
||||
cp=md;
|
||||
l=c->A; l2c(l,cp);
|
||||
l=c->B; l2c(l,cp);
|
||||
l=c->C; l2c(l,cp);
|
||||
l=c->D; l2c(l,cp);
|
||||
|
||||
/* clear stuff, md5_block may be leaving some stuff on the stack
|
||||
* but I'm not worried :-) */
|
||||
c->num=0;
|
||||
/* memset((char *)&c,0,sizeof(c));*/
|
||||
}
|
||||
|
||||
#ifdef undef
|
||||
int printit(l)
|
||||
unsigned long *l;
|
||||
{
|
||||
int i,ii;
|
||||
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
for (ii=0; ii<8; ii++)
|
||||
{
|
||||
fprintf(stderr,"%08lx ",l[i*8+ii]);
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* USE_MD5 */
|
||||
@@ -1,190 +0,0 @@
|
||||
/* crypto/md/md5_locl.h */
|
||||
/* Copyright (C) 1995-1997 Eric Young ([email protected])
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young ([email protected]).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson ([email protected]).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young ([email protected])"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson ([email protected])"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "md5.h"
|
||||
|
||||
#define ULONG unsigned long
|
||||
#define UCHAR unsigned char
|
||||
#define UINT unsigned int
|
||||
|
||||
#if defined(NOCONST)
|
||||
#define const
|
||||
#endif
|
||||
|
||||
#undef c2l
|
||||
#define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \
|
||||
l|=(((unsigned long)(*((c)++)))<< 8), \
|
||||
l|=(((unsigned long)(*((c)++)))<<16), \
|
||||
l|=(((unsigned long)(*((c)++)))<<24))
|
||||
|
||||
#undef p_c2l
|
||||
#define p_c2l(c,l,n) { \
|
||||
switch (n) { \
|
||||
case 0: l =((unsigned long)(*((c)++))); \
|
||||
case 1: l|=((unsigned long)(*((c)++)))<< 8; \
|
||||
case 2: l|=((unsigned long)(*((c)++)))<<16; \
|
||||
case 3: l|=((unsigned long)(*((c)++)))<<24; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* NOTE the pointer is not incremented at the end of this */
|
||||
#undef c2l_p
|
||||
#define c2l_p(c,l,n) { \
|
||||
l=0; \
|
||||
(c)+=n; \
|
||||
switch (n) { \
|
||||
case 3: l =((unsigned long)(*(--(c))))<<16; \
|
||||
case 2: l|=((unsigned long)(*(--(c))))<< 8; \
|
||||
case 1: l|=((unsigned long)(*(--(c)))) ; \
|
||||
} \
|
||||
}
|
||||
|
||||
#undef p_c2l_p
|
||||
#define p_c2l_p(c,l,sc,len) { \
|
||||
switch (sc) \
|
||||
{ \
|
||||
case 0: l =((unsigned long)(*((c)++))); \
|
||||
if (--len == 0U) break; \
|
||||
case 1: l|=((unsigned long)(*((c)++)))<< 8; \
|
||||
if (--len == 0U) break; \
|
||||
case 2: l|=((unsigned long)(*((c)++)))<<16; \
|
||||
} \
|
||||
}
|
||||
|
||||
#undef l2c
|
||||
#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
|
||||
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
|
||||
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
|
||||
*((c)++)=(unsigned char)(((l)>>24)&0xff))
|
||||
|
||||
/* NOTE - c is not incremented as per l2c */
|
||||
#undef l2cn
|
||||
#define l2cn(l1,l2,c,n) { \
|
||||
c+=n; \
|
||||
switch (n) { \
|
||||
case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
|
||||
case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
|
||||
case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
|
||||
case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \
|
||||
case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
|
||||
case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
|
||||
case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
|
||||
case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* A nice byte order reversal from Wei Dai <[email protected]> */
|
||||
#if defined(WIN32)
|
||||
/* 5 instructions with rotate instruction, else 9 */
|
||||
#define Endian_Reverse32(a) \
|
||||
{ \
|
||||
unsigned long l=(a); \
|
||||
(a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \
|
||||
}
|
||||
#else
|
||||
/* 6 instructions with rotate instruction, else 8 */
|
||||
#define Endian_Reverse32(a) \
|
||||
{ \
|
||||
unsigned long l=(a); \
|
||||
l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \
|
||||
(a)=ROTATE(l,16L); \
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
|
||||
#define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
|
||||
*/
|
||||
|
||||
/* As pointed out by Wei Dai <[email protected]>, the above can be
|
||||
* simplified to the code below. Wei attributes these optimisations
|
||||
* to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
|
||||
*/
|
||||
#define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
|
||||
#define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
|
||||
#define H(x,y,z) ((x) ^ (y) ^ (z))
|
||||
#define I(x,y,z) (((x) | (~(z))) ^ (y))
|
||||
|
||||
#undef ROTATE
|
||||
#if defined(WIN32)
|
||||
#define ROTATE(a,n) _lrotl(a,n)
|
||||
#else
|
||||
#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
|
||||
#endif
|
||||
|
||||
|
||||
#define R0(a,b,c,d,k,s,t) { \
|
||||
a+=((k)+(t)+F((b),(c),(d))); \
|
||||
a=ROTATE(a,s); \
|
||||
a+=b; };\
|
||||
|
||||
#define R1(a,b,c,d,k,s,t) { \
|
||||
a+=((k)+(t)+G((b),(c),(d))); \
|
||||
a=ROTATE(a,s); \
|
||||
a+=b; };
|
||||
|
||||
#define R2(a,b,c,d,k,s,t) { \
|
||||
a+=((k)+(t)+H((b),(c),(d))); \
|
||||
a=ROTATE(a,s); \
|
||||
a+=b; };
|
||||
|
||||
#define R3(a,b,c,d,k,s,t) { \
|
||||
a+=((k)+(t)+I((b),(c),(d))); \
|
||||
a=ROTATE(a,s); \
|
||||
a+=b; };
|
||||
@@ -1,350 +0,0 @@
|
||||
static const char rcsid[] = "$Header: /proj/cvs/prod/bind9/lib/bind/dst/support.c,v 1.2.2.1 2001/11/02 22:25:29 gson Exp $";
|
||||
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* dst_s_verify_str()
|
||||
* Validate that the input string(*str) is at the head of the input
|
||||
* buffer(**buf). If so, move the buffer head pointer (*buf) to
|
||||
* the first byte of data following the string(*str).
|
||||
* Parameters
|
||||
* buf Input buffer.
|
||||
* str Input string.
|
||||
* Return
|
||||
* 0 *str is not the head of **buff
|
||||
* 1 *str is the head of **buff, *buf is is advanced to
|
||||
* the tail of **buf.
|
||||
*/
|
||||
|
||||
int
|
||||
dst_s_verify_str(const char **buf, const char *str)
|
||||
{
|
||||
int b, s;
|
||||
if (*buf == NULL) /* error checks */
|
||||
return (0);
|
||||
if (str == NULL || *str == '\0')
|
||||
return (1);
|
||||
|
||||
b = strlen(*buf); /* get length of strings */
|
||||
s = strlen(str);
|
||||
if (s > b || strncmp(*buf, str, s)) /* check if same */
|
||||
return (0); /* not a match */
|
||||
(*buf) += s; /* advance pointer */
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_s_calculate_bits
|
||||
* Given a binary number represented in a u_char[], determine
|
||||
* the number of significant bits used.
|
||||
* Parameters
|
||||
* str An input character string containing a binary number.
|
||||
* max_bits The maximum possible significant bits.
|
||||
* Return
|
||||
* N The number of significant bits in str.
|
||||
*/
|
||||
|
||||
int
|
||||
dst_s_calculate_bits(const u_char *str, const int max_bits)
|
||||
{
|
||||
const u_char *p = str;
|
||||
u_char i, j = 0x80;
|
||||
int bits;
|
||||
for (bits = max_bits; *p == 0x00 && bits > 0; p++)
|
||||
bits -= 8;
|
||||
for (i = *p; (i & j) != j; j >>= 1)
|
||||
bits--;
|
||||
return (bits);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* calculates a checksum used in dst for an id.
|
||||
* takes an array of bytes and a length.
|
||||
* returns a 16 bit checksum.
|
||||
*/
|
||||
u_int16_t
|
||||
dst_s_id_calc(const u_char *key, const int keysize)
|
||||
{
|
||||
u_int32_t ac;
|
||||
const u_char *kp = key;
|
||||
int size = keysize;
|
||||
|
||||
if (!key || (keysize <= 0))
|
||||
return (-1);
|
||||
|
||||
for (ac = 0; size > 1; size -= 2, kp += 2)
|
||||
ac += ((*kp) << 8) + *(kp + 1);
|
||||
|
||||
if (size > 0)
|
||||
ac += ((*kp) << 8);
|
||||
ac += (ac >> 16) & 0xffff;
|
||||
|
||||
return (ac & 0xffff);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record
|
||||
* rdata
|
||||
* Input:
|
||||
* dns_key_rdata: the raw data in wire format
|
||||
* rdata_len: the size of the input data
|
||||
* Output:
|
||||
* the key footprint/id calculated from the key data
|
||||
*/
|
||||
u_int16_t
|
||||
dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len)
|
||||
{
|
||||
if (!dns_key_rdata)
|
||||
return 0;
|
||||
|
||||
/* compute id */
|
||||
if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */
|
||||
return dst_s_get_int16((const u_char *)
|
||||
&dns_key_rdata[rdata_len - 3]);
|
||||
else if (dns_key_rdata[3] == KEY_HMAC_MD5)
|
||||
/* compatibility */
|
||||
return 0;
|
||||
else
|
||||
/* compute a checksum on the key part of the key rr */
|
||||
return dst_s_id_calc(dns_key_rdata, rdata_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_s_get_int16
|
||||
* This routine extracts a 16 bit integer from a two byte character
|
||||
* string. The character string is assumed to be in network byte
|
||||
* order and may be unaligned. The number returned is in host order.
|
||||
* Parameter
|
||||
* buf A two byte character string.
|
||||
* Return
|
||||
* The converted integer value.
|
||||
*/
|
||||
|
||||
u_int16_t
|
||||
dst_s_get_int16(const u_char *buf)
|
||||
{
|
||||
register u_int16_t a = 0;
|
||||
a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
|
||||
return (a);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_s_get_int32
|
||||
* This routine extracts a 32 bit integer from a four byte character
|
||||
* string. The character string is assumed to be in network byte
|
||||
* order and may be unaligned. The number returned is in host order.
|
||||
* Parameter
|
||||
* buf A four byte character string.
|
||||
* Return
|
||||
* The converted integer value.
|
||||
*/
|
||||
|
||||
u_int32_t
|
||||
dst_s_get_int32(const u_char *buf)
|
||||
{
|
||||
register u_int32_t a = 0;
|
||||
a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) |
|
||||
((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3]));
|
||||
return (a);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_s_put_int16
|
||||
* Take a 16 bit integer and store the value in a two byte
|
||||
* character string. The integer is assumed to be in network
|
||||
* order and the string is returned in host order.
|
||||
*
|
||||
* Parameters
|
||||
* buf Storage for a two byte character string.
|
||||
* val 16 bit integer.
|
||||
*/
|
||||
|
||||
void
|
||||
dst_s_put_int16(u_int8_t *buf, const u_int16_t val)
|
||||
{
|
||||
buf[0] = (u_int8_t)(val >> 8);
|
||||
buf[1] = (u_int8_t)(val);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_s_put_int32
|
||||
* Take a 32 bit integer and store the value in a four byte
|
||||
* character string. The integer is assumed to be in network
|
||||
* order and the string is returned in host order.
|
||||
*
|
||||
* Parameters
|
||||
* buf Storage for a four byte character string.
|
||||
* val 32 bit integer.
|
||||
*/
|
||||
|
||||
void
|
||||
dst_s_put_int32(u_int8_t *buf, const u_int32_t val)
|
||||
{
|
||||
buf[0] = (u_int8_t)(val >> 24);
|
||||
buf[1] = (u_int8_t)(val >> 16);
|
||||
buf[2] = (u_int8_t)(val >> 8);
|
||||
buf[3] = (u_int8_t)(val);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_s_filename_length
|
||||
*
|
||||
* This function returns the number of bytes needed to hold the
|
||||
* filename for a key file. '/', '\' and ':' are not allowed.
|
||||
* form: K<keyname>+<alg>+<id>.<suffix>
|
||||
*
|
||||
* Returns 0 if the filename would contain either '\', '/' or ':'
|
||||
*/
|
||||
size_t
|
||||
dst_s_filename_length(const char *name, const char *suffix)
|
||||
{
|
||||
if (name == NULL)
|
||||
return (0);
|
||||
if (strrchr(name, '\\'))
|
||||
return (0);
|
||||
if (strrchr(name, '/'))
|
||||
return (0);
|
||||
if (strrchr(name, ':'))
|
||||
return (0);
|
||||
if (suffix == NULL)
|
||||
return (0);
|
||||
if (strrchr(suffix, '\\'))
|
||||
return (0);
|
||||
if (strrchr(suffix, '/'))
|
||||
return (0);
|
||||
if (strrchr(suffix, ':'))
|
||||
return (0);
|
||||
return (1 + strlen(name) + 6 + strlen(suffix));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_s_build_filename ()
|
||||
* Builds a key filename from the key name, it's id, and a
|
||||
* suffix. '\', '/' and ':' are not allowed. fA filename is of the
|
||||
* form: K<keyname><id>.<suffix>
|
||||
* form: K<keyname>+<alg>+<id>.<suffix>
|
||||
*
|
||||
* Returns -1 if the conversion fails:
|
||||
* if the filename would be too long for space allotted
|
||||
* if the filename would contain a '\', '/' or ':'
|
||||
* Returns 0 on success
|
||||
*/
|
||||
|
||||
int
|
||||
dst_s_build_filename(char *filename, const char *name, u_int16_t id,
|
||||
int alg, const char *suffix, size_t filename_length)
|
||||
{
|
||||
u_int32_t my_id;
|
||||
if (filename == NULL)
|
||||
return (-1);
|
||||
memset(filename, 0, filename_length);
|
||||
if (name == NULL)
|
||||
return (-1);
|
||||
if (suffix == NULL)
|
||||
return (-1);
|
||||
if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
|
||||
return (-1);
|
||||
my_id = id;
|
||||
sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
|
||||
(const char *) suffix);
|
||||
if (strrchr(filename, '/'))
|
||||
return (-1);
|
||||
if (strrchr(filename, '\\'))
|
||||
return (-1);
|
||||
if (strrchr(filename, ':'))
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_s_fopen ()
|
||||
* Open a file in the dst_path directory. If perm is specified, the
|
||||
* file is checked for existence first, and not opened if it exists.
|
||||
* Parameters
|
||||
* filename File to open
|
||||
* mode Mode to open the file (passed directly to fopen)
|
||||
* perm File permission, if creating a new file.
|
||||
* Returns
|
||||
* NULL Failure
|
||||
* NON-NULL (FILE *) of opened file.
|
||||
*/
|
||||
FILE *
|
||||
dst_s_fopen(const char *filename, const char *mode, int perm)
|
||||
{
|
||||
FILE *fp;
|
||||
char pathname[PATH_MAX];
|
||||
size_t plen = sizeof(pathname);
|
||||
|
||||
if (*dst_path != '\0') {
|
||||
strcpy(pathname, dst_path);
|
||||
plen -= strlen(pathname);
|
||||
}
|
||||
else
|
||||
pathname[0] = '\0';
|
||||
|
||||
if (plen > strlen(filename))
|
||||
strncpy(&pathname[PATH_MAX - plen], filename, plen-1);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
fp = fopen(pathname, mode);
|
||||
if (perm)
|
||||
chmod(pathname, perm);
|
||||
return (fp);
|
||||
}
|
||||
|
||||
void
|
||||
dst_s_dump(const int mode, const u_char *data, const int size,
|
||||
const char *msg)
|
||||
{
|
||||
UNUSED(data);
|
||||
|
||||
if (size > 0) {
|
||||
#ifdef LONG_TEST
|
||||
static u_char scratch[1000];
|
||||
int n ;
|
||||
n = b64_ntop(data, scratch, size, sizeof(scratch));
|
||||
printf("%s: %x %d %s\n", msg, mode, n, scratch);
|
||||
#else
|
||||
printf("%s,%x %d\n", msg, mode, size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* Ascii internet address interpretation routine.
|
||||
* The value returned is in network order.
|
||||
*/
|
||||
u_long
|
||||
inet_addr(const char *cp) {
|
||||
struct in_addr val;
|
||||
|
||||
if (inet_aton(cp, &val))
|
||||
return (val.s_addr);
|
||||
return (INADDR_NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether "cp" is a valid ascii representation
|
||||
* of an Internet address and convert to a binary address.
|
||||
* Returns 1 if the address is valid, 0 if not.
|
||||
* This replaces inet_addr, the return value from which
|
||||
* cannot distinguish between failure and a local broadcast address.
|
||||
*/
|
||||
int
|
||||
inet_aton(const char *cp, struct in_addr *addr) {
|
||||
u_long val;
|
||||
int base, n;
|
||||
char c;
|
||||
u_int8_t parts[4];
|
||||
u_int8_t *pp = parts;
|
||||
int digit;
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, isdigit=decimal.
|
||||
*/
|
||||
if (!isdigit((unsigned char)c))
|
||||
return (0);
|
||||
val = 0; base = 10; digit = 0;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X')
|
||||
base = 16, c = *++cp;
|
||||
else {
|
||||
base = 8;
|
||||
digit = 1 ;
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (isascii(c) && isdigit((unsigned char)c)) {
|
||||
if (base == 8 && (c == '8' || c == '9'))
|
||||
return (0);
|
||||
val = (val * base) + (c - '0');
|
||||
c = *++cp;
|
||||
digit = 1;
|
||||
} else if (base == 16 && isascii(c) &&
|
||||
isxdigit((unsigned char)c)) {
|
||||
val = (val << 4) |
|
||||
(c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
digit = 1;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3 || val > 0xffU)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && (!isascii(c) || !isspace((unsigned char)c)))
|
||||
return (0);
|
||||
/*
|
||||
* Did we get a valid digit?
|
||||
*/
|
||||
if (!digit)
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
n = pp - parts + 1;
|
||||
switch (n) {
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffffU)
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffffU)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xffU)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
}
|
||||
if (addr != NULL)
|
||||
addr->s_addr = htonl(val);
|
||||
return (1);
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) ((size_t)sprintf x)
|
||||
#endif
|
||||
|
||||
static char * inet_cidr_ntop_ipv4 __P((const u_char *src, int bits,
|
||||
char *dst, size_t size));
|
||||
static char * inet_cidr_ntop_ipv6 __P((const u_char *src, int bits,
|
||||
char *dst, size_t size));
|
||||
|
||||
/*
|
||||
* char *
|
||||
* inet_cidr_ntop(af, src, bits, dst, size)
|
||||
* convert network address from network to presentation format.
|
||||
* "src"'s size is determined from its "af".
|
||||
* return:
|
||||
* pointer to dst, or NULL if an error occurred (check errno).
|
||||
* note:
|
||||
* 192.5.5.1/28 has a nonzero host part, which means it isn't a network
|
||||
* as called for by inet_net_ntop() but it can be a host address with
|
||||
* an included netmask.
|
||||
* author:
|
||||
* Paul Vixie (ISC), October 1998
|
||||
*/
|
||||
char *
|
||||
inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) {
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_cidr_ntop_ipv4(src, bits, dst, size));
|
||||
case AF_INET6:
|
||||
return (inet_cidr_ntop_ipv6(src, bits, dst, size));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
decoct(const u_char *src, int bytes, char *dst, size_t size) {
|
||||
char *odst = dst;
|
||||
char *t;
|
||||
int b;
|
||||
|
||||
for (b = 1; b <= bytes; b++) {
|
||||
if (size < sizeof "255.")
|
||||
return (0);
|
||||
t = dst;
|
||||
dst += SPRINTF((dst, "%u", *src++));
|
||||
if (b != bytes) {
|
||||
*dst++ = '.';
|
||||
*dst = '\0';
|
||||
}
|
||||
size -= (size_t)(dst - t);
|
||||
}
|
||||
return (dst - odst);
|
||||
}
|
||||
|
||||
/*
|
||||
* static char *
|
||||
* inet_cidr_ntop_ipv4(src, bits, dst, size)
|
||||
* convert IPv4 network address from network to presentation format.
|
||||
* "src"'s size is determined from its "af".
|
||||
* return:
|
||||
* pointer to dst, or NULL if an error occurred (check errno).
|
||||
* note:
|
||||
* network byte order assumed. this means 192.5.5.240/28 has
|
||||
* 0b11110000 in its fourth octet.
|
||||
* author:
|
||||
* Paul Vixie (ISC), October 1998
|
||||
*/
|
||||
static char *
|
||||
inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) {
|
||||
char *odst = dst;
|
||||
size_t len = 4;
|
||||
size_t b;
|
||||
size_t bytes;
|
||||
|
||||
if ((bits < -1) || (bits > 32)) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Find number of significant bytes in address. */
|
||||
if (bits == -1)
|
||||
len = 4;
|
||||
else
|
||||
for (len = 1, b = 1 ; b < 4U; b++)
|
||||
if (*(src + b))
|
||||
len = b + 1;
|
||||
|
||||
/* Format whole octets plus nonzero trailing octets. */
|
||||
bytes = (((bits <= 0) ? 1 : bits) + 7) / 8;
|
||||
if (len > bytes)
|
||||
bytes = len;
|
||||
b = decoct(src, bytes, dst, size);
|
||||
if (b == 0U)
|
||||
goto emsgsize;
|
||||
dst += b;
|
||||
size -= b;
|
||||
|
||||
if (bits != -1) {
|
||||
/* Format CIDR /width. */
|
||||
if (size < sizeof "/32")
|
||||
goto emsgsize;
|
||||
dst += SPRINTF((dst, "/%u", bits));
|
||||
}
|
||||
|
||||
return (odst);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
|
||||
/*
|
||||
* Note that int32_t and int16_t need only be "at least" large enough
|
||||
* to contain a value of the specified size. On some systems, like
|
||||
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||
* Keep this in mind if you think this function should have been coded
|
||||
* to use pointer overlays. All the world's not a VAX.
|
||||
*/
|
||||
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
|
||||
char *tp;
|
||||
struct { int base, len; } best, cur;
|
||||
u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
|
||||
int i;
|
||||
|
||||
if ((bits < -1) || (bits > 128)) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Preprocess:
|
||||
* Copy the input (bytewise) array into a wordwise array.
|
||||
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||
*/
|
||||
memset(words, '\0', sizeof words);
|
||||
for (i = 0; i < NS_IN6ADDRSZ; i++)
|
||||
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
best.base = -1;
|
||||
cur.base = -1;
|
||||
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
|
||||
if (words[i] == 0) {
|
||||
if (cur.base == -1)
|
||||
cur.base = i, cur.len = 1;
|
||||
else
|
||||
cur.len++;
|
||||
} else {
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
cur.base = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
}
|
||||
if (best.base != -1 && best.len < 2)
|
||||
best.base = -1;
|
||||
|
||||
/*
|
||||
* Format the result.
|
||||
*/
|
||||
tp = tmp;
|
||||
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
|
||||
/* Are we inside the best run of 0x00's? */
|
||||
if (best.base != -1 && i >= best.base &&
|
||||
i < (best.base + best.len)) {
|
||||
if (i == best.base)
|
||||
*tp++ = ':';
|
||||
continue;
|
||||
}
|
||||
/* Are we following an initial run of 0x00s or any real hex? */
|
||||
if (i != 0)
|
||||
*tp++ = ':';
|
||||
/* Is this address an encapsulated IPv4? */
|
||||
if (i == 6 && best.base == 0 && (best.len == 6 ||
|
||||
(best.len == 7 && words[7] != 0x0001) ||
|
||||
(best.len == 5 && words[5] == 0xffff))) {
|
||||
int n;
|
||||
|
||||
if (src[15] || bits == -1 || bits > 120)
|
||||
n = 4;
|
||||
else if (src[14] || bits > 112)
|
||||
n = 3;
|
||||
else
|
||||
n = 2;
|
||||
n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp));
|
||||
if (n == 0) {
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += SPRINTF((tp, "%x", words[i]));
|
||||
}
|
||||
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) ==
|
||||
(NS_IN6ADDRSZ / NS_INT16SZ))
|
||||
*tp++ = ':';
|
||||
*tp = '\0';
|
||||
|
||||
if (bits != -1)
|
||||
tp += SPRINTF((tp, "/%u", bits));
|
||||
|
||||
/*
|
||||
* Check for overflow, copy, and we're done.
|
||||
*/
|
||||
if ((size_t)(tp - tmp) > size) {
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
||||
@@ -1,275 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) ((size_t)sprintf x)
|
||||
#endif
|
||||
|
||||
static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst,
|
||||
int *bits, int ipv6));
|
||||
static int inet_cidr_pton_ipv6 __P((const char *src, u_char *dst,
|
||||
int *bits));
|
||||
|
||||
static int getbits(const char *, int ipv6);
|
||||
|
||||
/*
|
||||
* int
|
||||
* inet_cidr_pton(af, src, dst, *bits)
|
||||
* convert network address from presentation to network format.
|
||||
* accepts inet_pton()'s input for this "af" plus trailing "/CIDR".
|
||||
* "dst" is assumed large enough for its "af". "bits" is set to the
|
||||
* /CIDR prefix length, which can have defaults (like /32 for IPv4).
|
||||
* return:
|
||||
* -1 if an error occurred (inspect errno; ENOENT means bad format).
|
||||
* 0 if successful conversion occurred.
|
||||
* note:
|
||||
* 192.5.5.1/28 has a nonzero host part, which means it isn't a network
|
||||
* as called for by inet_net_pton() but it can be a host address with
|
||||
* an included netmask.
|
||||
* author:
|
||||
* Paul Vixie (ISC), October 1998
|
||||
*/
|
||||
int
|
||||
inet_cidr_pton(int af, const char *src, void *dst, int *bits) {
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_cidr_pton_ipv4(src, dst, bits, 0));
|
||||
case AF_INET6:
|
||||
return (inet_cidr_pton_ipv6(src, dst, bits));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
static const char digits[] = "0123456789";
|
||||
|
||||
static int
|
||||
inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) {
|
||||
const u_char *odst = dst;
|
||||
int n, ch, tmp, bits;
|
||||
size_t size = 4;
|
||||
|
||||
/* Get the mantissa. */
|
||||
while (ch = *src++, (isascii(ch) && isdigit(ch))) {
|
||||
tmp = 0;
|
||||
do {
|
||||
n = strchr(digits, ch) - digits;
|
||||
INSIST(n >= 0 && n <= 9);
|
||||
tmp *= 10;
|
||||
tmp += n;
|
||||
if (tmp > 255)
|
||||
goto enoent;
|
||||
} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
|
||||
if (size-- == 0U)
|
||||
goto emsgsize;
|
||||
*dst++ = (u_char) tmp;
|
||||
if (ch == '\0' || ch == '/')
|
||||
break;
|
||||
if (ch != '.')
|
||||
goto enoent;
|
||||
}
|
||||
|
||||
/* Get the prefix length if any. */
|
||||
bits = -1;
|
||||
if (ch == '/' && dst > odst) {
|
||||
bits = getbits(src, ipv6);
|
||||
if (bits == -2)
|
||||
goto enoent;
|
||||
} else if (ch != '\0')
|
||||
goto enoent;
|
||||
|
||||
/* Prefix length can default to /32 only if all four octets spec'd. */
|
||||
if (bits == -1) {
|
||||
if (dst - odst == 4)
|
||||
bits = ipv6 ? 128 : 32;
|
||||
else
|
||||
goto enoent;
|
||||
}
|
||||
|
||||
/* If nothing was written to the destination, we found no address. */
|
||||
if (dst == odst)
|
||||
goto enoent;
|
||||
|
||||
/* If prefix length overspecifies mantissa, life is bad. */
|
||||
if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst))
|
||||
goto enoent;
|
||||
|
||||
/* Extend address to four octets. */
|
||||
while (size-- > 0U)
|
||||
*dst++ = 0;
|
||||
|
||||
*pbits = bits;
|
||||
return (0);
|
||||
|
||||
enoent:
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) {
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *xdigits, *curtok;
|
||||
int ch, saw_xdigit;
|
||||
u_int val;
|
||||
int bits;
|
||||
|
||||
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
|
||||
endp = tp + NS_IN6ADDRSZ;
|
||||
colonp = NULL;
|
||||
/* Leading :: requires some special handling. */
|
||||
if (*src == ':')
|
||||
if (*++src != ':')
|
||||
return (0);
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
bits = -1;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if (pch != NULL) {
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':') {
|
||||
curtok = src;
|
||||
if (!saw_xdigit) {
|
||||
if (colonp)
|
||||
return (0);
|
||||
colonp = tp;
|
||||
continue;
|
||||
} else if (*src == '\0') {
|
||||
return (0);
|
||||
}
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
|
||||
inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) {
|
||||
tp += NS_INADDRSZ;
|
||||
saw_xdigit = 0;
|
||||
break; /* '\0' was seen by inet_pton4(). */
|
||||
}
|
||||
if (ch == '/') {
|
||||
bits = getbits(src, 1);
|
||||
if (bits == -2)
|
||||
goto enoent;
|
||||
break;
|
||||
}
|
||||
goto enoent;
|
||||
}
|
||||
if (saw_xdigit) {
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
goto emsgsize;
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
}
|
||||
if (colonp != NULL) {
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
const int n = tp - colonp;
|
||||
int i;
|
||||
|
||||
if (tp == endp)
|
||||
goto enoent;
|
||||
for (i = 1; i <= n; i++) {
|
||||
endp[- i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
|
||||
memcpy(dst, tmp, NS_IN6ADDRSZ);
|
||||
|
||||
*pbits = bits;
|
||||
return (0);
|
||||
|
||||
enoent:
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
getbits(const char *src, int ipv6) {
|
||||
int bits = 0;
|
||||
char *cp, ch;
|
||||
|
||||
if (*src == '\0') /* syntax */
|
||||
return (-2);
|
||||
do {
|
||||
ch = *src++;
|
||||
cp = strchr(digits, ch);
|
||||
if (cp == NULL) /* syntax */
|
||||
return (-2);
|
||||
bits *= 10;
|
||||
bits += cp - digits;
|
||||
if (bits == 0 && *src != '\0') /* no leading zeros */
|
||||
return (-2);
|
||||
if (bits > (ipv6 ? 128 : 32)) /* range error */
|
||||
return (-2);
|
||||
} while (*src != '\0');
|
||||
|
||||
return (bits);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1995-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
const struct in6_addr isc_in6addr_any = IN6ADDR_ANY_INIT;
|
||||
const struct in6_addr isc_in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* Return the local network address portion of an
|
||||
* internet address; handles class a/b/c network
|
||||
* number formats.
|
||||
*/
|
||||
u_long
|
||||
inet_lnaof(in)
|
||||
struct in_addr in;
|
||||
{
|
||||
register u_long i = ntohl(in.s_addr);
|
||||
|
||||
if (IN_CLASSA(i))
|
||||
return ((i)&IN_CLASSA_HOST);
|
||||
else if (IN_CLASSB(i))
|
||||
return ((i)&IN_CLASSB_HOST);
|
||||
else
|
||||
return ((i)&IN_CLASSC_HOST);
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* Formulate an Internet address from network + host. Used in
|
||||
* building addresses stored in the ifnet structure.
|
||||
*/
|
||||
struct in_addr
|
||||
inet_makeaddr(net, host)
|
||||
u_long net, host;
|
||||
{
|
||||
struct in_addr a;
|
||||
|
||||
if (net < 128U)
|
||||
a.s_addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
|
||||
else if (net < 65536U)
|
||||
a.s_addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
|
||||
else if (net < 16777216L)
|
||||
a.s_addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
|
||||
else
|
||||
a.s_addr = net | host;
|
||||
a.s_addr = htonl(a.s_addr);
|
||||
return (a);
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) ((size_t)sprintf x)
|
||||
#endif
|
||||
|
||||
static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits,
|
||||
char *dst, size_t size));
|
||||
static char * inet_net_ntop_ipv6 __P((const u_char *src, int bits,
|
||||
char *dst, size_t size));
|
||||
|
||||
/*
|
||||
* char *
|
||||
* inet_net_ntop(af, src, bits, dst, size)
|
||||
* convert network number from network to presentation format.
|
||||
* generates CIDR style result always.
|
||||
* return:
|
||||
* pointer to dst, or NULL if an error occurred (check errno).
|
||||
* author:
|
||||
* Paul Vixie (ISC), July 1996
|
||||
*/
|
||||
char *
|
||||
inet_net_ntop(af, src, bits, dst, size)
|
||||
int af;
|
||||
const void *src;
|
||||
int bits;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_net_ntop_ipv4(src, bits, dst, size));
|
||||
case AF_INET6:
|
||||
return (inet_net_ntop_ipv6(src, bits, dst, size));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* static char *
|
||||
* inet_net_ntop_ipv4(src, bits, dst, size)
|
||||
* convert IPv4 network number from network to presentation format.
|
||||
* generates CIDR style result always.
|
||||
* return:
|
||||
* pointer to dst, or NULL if an error occurred (check errno).
|
||||
* note:
|
||||
* network byte order assumed. this means 192.5.5.240/28 has
|
||||
* 0b11110000 in its fourth octet.
|
||||
* author:
|
||||
* Paul Vixie (ISC), July 1996
|
||||
*/
|
||||
static char *
|
||||
inet_net_ntop_ipv4(src, bits, dst, size)
|
||||
const u_char *src;
|
||||
int bits;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
char *odst = dst;
|
||||
char *t;
|
||||
u_int m;
|
||||
int b;
|
||||
|
||||
if (bits < 0 || bits > 32) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (bits == 0) {
|
||||
if (size < sizeof "0")
|
||||
goto emsgsize;
|
||||
*dst++ = '0';
|
||||
size--;
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
/* Format whole octets. */
|
||||
for (b = bits / 8; b > 0; b--) {
|
||||
if (size <= sizeof "255.")
|
||||
goto emsgsize;
|
||||
t = dst;
|
||||
dst += SPRINTF((dst, "%u", *src++));
|
||||
if (b > 1) {
|
||||
*dst++ = '.';
|
||||
*dst = '\0';
|
||||
}
|
||||
size -= (size_t)(dst - t);
|
||||
}
|
||||
|
||||
/* Format partial octet. */
|
||||
b = bits % 8;
|
||||
if (b > 0) {
|
||||
if (size <= sizeof ".255")
|
||||
goto emsgsize;
|
||||
t = dst;
|
||||
if (dst != odst)
|
||||
*dst++ = '.';
|
||||
m = ((1 << b) - 1) << (8 - b);
|
||||
dst += SPRINTF((dst, "%u", *src & m));
|
||||
size -= (size_t)(dst - t);
|
||||
}
|
||||
|
||||
/* Format CIDR /width. */
|
||||
if (size <= sizeof "/32")
|
||||
goto emsgsize;
|
||||
dst += SPRINTF((dst, "/%u", bits));
|
||||
return (odst);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* static char *
|
||||
* inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
|
||||
* convert IPv6 network number from network to presentation format.
|
||||
* generates CIDR style result always. Picks the shortest representation
|
||||
* unless the IP is really IPv4.
|
||||
* always prints specified number of bits (bits).
|
||||
* return:
|
||||
* pointer to dst, or NULL if an error occurred (check errno).
|
||||
* note:
|
||||
* network byte order assumed. this means 192.5.5.240/28 has
|
||||
* 0x11110000 in its fourth octet.
|
||||
* author:
|
||||
* Vadim Kogan (UCB), June 2001
|
||||
* Original version (IPv4) by Paul Vixie (ISC), July 1996
|
||||
*/
|
||||
|
||||
static char *
|
||||
inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
|
||||
u_int m;
|
||||
int b;
|
||||
int p;
|
||||
int zero_s, zero_l, tmp_zero_s, tmp_zero_l;
|
||||
int i;
|
||||
int is_ipv4 = 0;
|
||||
unsigned char inbuf[16];
|
||||
char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
|
||||
char *cp;
|
||||
int words;
|
||||
u_char *s;
|
||||
|
||||
if (bits < 0 || bits > 128) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
cp = outbuf;
|
||||
|
||||
if (bits == 0) {
|
||||
*cp++ = ':';
|
||||
*cp++ = ':';
|
||||
*cp = '\0';
|
||||
} else {
|
||||
/* Copy src to private buffer. Zero host part. */
|
||||
p = (bits + 7) / 8;
|
||||
memcpy(inbuf, src, p);
|
||||
memset(inbuf + p, 0, 16 - p);
|
||||
b = bits % 8;
|
||||
if (b != 0) {
|
||||
m = ~0 << (8 - b);
|
||||
inbuf[p-1] &= m;
|
||||
}
|
||||
|
||||
s = inbuf;
|
||||
|
||||
/* how many words need to be displayed in output */
|
||||
words = (bits + 15) / 16;
|
||||
if (words == 1)
|
||||
words = 2;
|
||||
|
||||
/* Find the longest substring of zero's */
|
||||
zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
|
||||
for (i = 0; i < (words * 2); i += 2) {
|
||||
if ((s[i] | s[i+1]) == 0) {
|
||||
if (tmp_zero_l == 0)
|
||||
tmp_zero_s = i / 2;
|
||||
tmp_zero_l++;
|
||||
} else {
|
||||
if (tmp_zero_l && zero_l < tmp_zero_l) {
|
||||
zero_s = tmp_zero_s;
|
||||
zero_l = tmp_zero_l;
|
||||
tmp_zero_l = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_zero_l && zero_l < tmp_zero_l) {
|
||||
zero_s = tmp_zero_s;
|
||||
zero_l = tmp_zero_l;
|
||||
}
|
||||
|
||||
if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
|
||||
((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
|
||||
((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
|
||||
is_ipv4 = 1;
|
||||
|
||||
/* Format whole words. */
|
||||
for (p = 0; p < words; p++) {
|
||||
if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) {
|
||||
/* Time to skip some zeros */
|
||||
if (p == zero_s)
|
||||
*cp++ = ':';
|
||||
if (p == words - 1)
|
||||
*cp++ = ':';
|
||||
s++;
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_ipv4 && p > 5 ) {
|
||||
*cp++ = (p == 6) ? ':' : '.';
|
||||
cp += SPRINTF((cp, "%u", *s++));
|
||||
/* we can potentially drop the last octet */
|
||||
if (p != 7 || bits > 120) {
|
||||
*cp++ = '.';
|
||||
cp += SPRINTF((cp, "%u", *s++));
|
||||
}
|
||||
} else {
|
||||
if (cp != outbuf)
|
||||
*cp++ = ':';
|
||||
cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
|
||||
s += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Format CIDR /width. */
|
||||
SPRINTF((cp, "/%u", bits));
|
||||
if (strlen(outbuf) + 1 > size)
|
||||
goto emsgsize;
|
||||
strcpy(dst, outbuf);
|
||||
|
||||
return (dst);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
@@ -1,405 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) ((size_t)sprintf x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* static int
|
||||
* inet_net_pton_ipv4(src, dst, size)
|
||||
* convert IPv4 network number from presentation to network format.
|
||||
* accepts hex octets, hex strings, decimal octets, and /CIDR.
|
||||
* "size" is in bytes and describes "dst".
|
||||
* return:
|
||||
* number of bits, either imputed classfully or specified with /CIDR,
|
||||
* or -1 if some failure occurred (check errno). ENOENT means it was
|
||||
* not an IPv4 network specification.
|
||||
* note:
|
||||
* network byte order assumed. this means 192.5.5.240/28 has
|
||||
* 0b11110000 in its fourth octet.
|
||||
* author:
|
||||
* Paul Vixie (ISC), June 1996
|
||||
*/
|
||||
static int
|
||||
inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
|
||||
static const char xdigits[] = "0123456789abcdef";
|
||||
static const char digits[] = "0123456789";
|
||||
int n, ch, tmp = 0, dirty, bits;
|
||||
const u_char *odst = dst;
|
||||
|
||||
ch = *src++;
|
||||
if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
|
||||
&& isascii((unsigned char)(src[1]))
|
||||
&& isxdigit((unsigned char)(src[1]))) {
|
||||
/* Hexadecimal: Eat nybble string. */
|
||||
if (size <= 0U)
|
||||
goto emsgsize;
|
||||
dirty = 0;
|
||||
src++; /* skip x or X. */
|
||||
while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
|
||||
if (isupper(ch))
|
||||
ch = tolower(ch);
|
||||
n = strchr(xdigits, ch) - xdigits;
|
||||
INSIST(n >= 0 && n <= 15);
|
||||
if (dirty == 0)
|
||||
tmp = n;
|
||||
else
|
||||
tmp = (tmp << 4) | n;
|
||||
if (++dirty == 2) {
|
||||
if (size-- <= 0U)
|
||||
goto emsgsize;
|
||||
*dst++ = (u_char) tmp;
|
||||
dirty = 0;
|
||||
}
|
||||
}
|
||||
if (dirty) { /* Odd trailing nybble? */
|
||||
if (size-- <= 0U)
|
||||
goto emsgsize;
|
||||
*dst++ = (u_char) (tmp << 4);
|
||||
}
|
||||
} else if (isascii(ch) && isdigit(ch)) {
|
||||
/* Decimal: eat dotted digit string. */
|
||||
for (;;) {
|
||||
tmp = 0;
|
||||
do {
|
||||
n = strchr(digits, ch) - digits;
|
||||
INSIST(n >= 0 && n <= 9);
|
||||
tmp *= 10;
|
||||
tmp += n;
|
||||
if (tmp > 255)
|
||||
goto enoent;
|
||||
} while ((ch = *src++) != '\0' &&
|
||||
isascii(ch) && isdigit(ch));
|
||||
if (size-- <= 0U)
|
||||
goto emsgsize;
|
||||
*dst++ = (u_char) tmp;
|
||||
if (ch == '\0' || ch == '/')
|
||||
break;
|
||||
if (ch != '.')
|
||||
goto enoent;
|
||||
ch = *src++;
|
||||
if (!isascii(ch) || !isdigit(ch))
|
||||
goto enoent;
|
||||
}
|
||||
} else
|
||||
goto enoent;
|
||||
|
||||
bits = -1;
|
||||
if (ch == '/' && isascii((unsigned char)(src[0])) &&
|
||||
isdigit((unsigned char)(src[0])) && dst > odst) {
|
||||
/* CIDR width specifier. Nothing can follow it. */
|
||||
ch = *src++; /* Skip over the /. */
|
||||
bits = 0;
|
||||
do {
|
||||
n = strchr(digits, ch) - digits;
|
||||
INSIST(n >= 0 && n <= 9);
|
||||
bits *= 10;
|
||||
bits += n;
|
||||
} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
|
||||
if (ch != '\0')
|
||||
goto enoent;
|
||||
if (bits > 32)
|
||||
goto emsgsize;
|
||||
}
|
||||
|
||||
/* Firey death and destruction unless we prefetched EOS. */
|
||||
if (ch != '\0')
|
||||
goto enoent;
|
||||
|
||||
/* If nothing was written to the destination, we found no address. */
|
||||
if (dst == odst)
|
||||
goto enoent;
|
||||
/* If no CIDR spec was given, infer width from net class. */
|
||||
if (bits == -1) {
|
||||
if (*odst >= 240) /* Class E */
|
||||
bits = 32;
|
||||
else if (*odst >= 224) /* Class D */
|
||||
bits = 8;
|
||||
else if (*odst >= 192) /* Class C */
|
||||
bits = 24;
|
||||
else if (*odst >= 128) /* Class B */
|
||||
bits = 16;
|
||||
else /* Class A */
|
||||
bits = 8;
|
||||
/* If imputed mask is narrower than specified octets, widen. */
|
||||
if (bits < ((dst - odst) * 8))
|
||||
bits = (dst - odst) * 8;
|
||||
/*
|
||||
* If there are no additional bits specified for a class D
|
||||
* address adjust bits to 4.
|
||||
*/
|
||||
if (bits == 8 && *odst == 224)
|
||||
bits = 4;
|
||||
}
|
||||
/* Extend network to cover the actual mask. */
|
||||
while (bits > ((dst - odst) * 8)) {
|
||||
if (size-- <= 0U)
|
||||
goto emsgsize;
|
||||
*dst++ = '\0';
|
||||
}
|
||||
return (bits);
|
||||
|
||||
enoent:
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
getbits(const char *src, int *bitsp) {
|
||||
static const char digits[] = "0123456789";
|
||||
int n;
|
||||
int val;
|
||||
char ch;
|
||||
|
||||
val = 0;
|
||||
n = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
pch = strchr(digits, ch);
|
||||
if (pch != NULL) {
|
||||
if (n++ != 0 && val == 0) /* no leading zeros */
|
||||
return (0);
|
||||
val *= 10;
|
||||
val += (pch - digits);
|
||||
if (val > 128) /* range */
|
||||
return (0);
|
||||
continue;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
if (n == 0)
|
||||
return (0);
|
||||
*bitsp = val;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
getv4(const char *src, u_char *dst, int *bitsp) {
|
||||
static const char digits[] = "0123456789";
|
||||
u_char *odst = dst;
|
||||
int n;
|
||||
u_int val;
|
||||
char ch;
|
||||
|
||||
val = 0;
|
||||
n = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
pch = strchr(digits, ch);
|
||||
if (pch != NULL) {
|
||||
if (n++ != 0 && val == 0) /* no leading zeros */
|
||||
return (0);
|
||||
val *= 10;
|
||||
val += (pch - digits);
|
||||
if (val > 255) /* range */
|
||||
return (0);
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' || ch == '/') {
|
||||
if (dst - odst > 3) /* too many octets? */
|
||||
return (0);
|
||||
*dst++ = val;
|
||||
if (ch == '/')
|
||||
return (getbits(src, bitsp));
|
||||
val = 0;
|
||||
n = 0;
|
||||
continue;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
if (n == 0)
|
||||
return (0);
|
||||
if (dst - odst > 3) /* too many octets? */
|
||||
return (0);
|
||||
*dst++ = val;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) {
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *xdigits, *curtok;
|
||||
int ch, saw_xdigit;
|
||||
u_int val;
|
||||
int digits;
|
||||
int bits;
|
||||
size_t bytes;
|
||||
int words;
|
||||
int ipv4;
|
||||
|
||||
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
|
||||
endp = tp + NS_IN6ADDRSZ;
|
||||
colonp = NULL;
|
||||
/* Leading :: requires some special handling. */
|
||||
if (*src == ':')
|
||||
if (*++src != ':')
|
||||
goto enoent;
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
digits = 0;
|
||||
bits = -1;
|
||||
ipv4 = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if (pch != NULL) {
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
if (++digits > 4)
|
||||
goto enoent;
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':') {
|
||||
curtok = src;
|
||||
if (!saw_xdigit) {
|
||||
if (colonp)
|
||||
goto enoent;
|
||||
colonp = tp;
|
||||
continue;
|
||||
} else if (*src == '\0')
|
||||
goto enoent;
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
digits = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
|
||||
getv4(curtok, tp, &bits) > 0) {
|
||||
tp += NS_INADDRSZ;
|
||||
saw_xdigit = 0;
|
||||
ipv4 = 1;
|
||||
break; /* '\0' was seen by inet_pton4(). */
|
||||
}
|
||||
if (ch == '/' && getbits(src, &bits) > 0)
|
||||
break;
|
||||
goto enoent;
|
||||
}
|
||||
if (saw_xdigit) {
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
goto enoent;
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
}
|
||||
if (bits == -1)
|
||||
bits = 128;
|
||||
|
||||
words = (bits + 15) / 16;
|
||||
if (words < 2)
|
||||
words = 2;
|
||||
if (ipv4)
|
||||
words = 8;
|
||||
endp = tmp + 2 * words;
|
||||
|
||||
if (colonp != NULL) {
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
const int n = tp - colonp;
|
||||
int i;
|
||||
|
||||
if (tp == endp)
|
||||
goto enoent;
|
||||
for (i = 1; i <= n; i++) {
|
||||
endp[- i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
if (tp != endp)
|
||||
goto enoent;
|
||||
|
||||
bytes = (bits + 7) / 8;
|
||||
if (bytes > size)
|
||||
goto emsgsize;
|
||||
memcpy(dst, tmp, bytes);
|
||||
return (bits);
|
||||
|
||||
enoent:
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* int
|
||||
* inet_net_pton(af, src, dst, size)
|
||||
* convert network number from presentation to network format.
|
||||
* accepts hex octets, hex strings, decimal octets, and /CIDR.
|
||||
* "size" is in bytes and describes "dst".
|
||||
* return:
|
||||
* number of bits, either imputed classfully or specified with /CIDR,
|
||||
* or -1 if some failure occurred (check errno). ENOENT means it was
|
||||
* not a valid network specification.
|
||||
* author:
|
||||
* Paul Vixie (ISC), June 1996
|
||||
*/
|
||||
int
|
||||
inet_net_pton(int af, const char *src, void *dst, size_t size) {
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_net_pton_ipv4(src, dst, size));
|
||||
case AF_INET6:
|
||||
return (inet_net_pton_ipv6(src, dst, size));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) ((size_t)sprintf x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* char *
|
||||
* inet_neta(src, dst, size)
|
||||
* format a u_long network number into presentation format.
|
||||
* return:
|
||||
* pointer to dst, or NULL if an error occurred (check errno).
|
||||
* note:
|
||||
* format of ``src'' is as for inet_network().
|
||||
* author:
|
||||
* Paul Vixie (ISC), July 1996
|
||||
*/
|
||||
char *
|
||||
inet_neta(src, dst, size)
|
||||
u_long src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
char *odst = dst;
|
||||
char *tp;
|
||||
|
||||
while (src & 0xffffffff) {
|
||||
u_char b = (src & 0xff000000) >> 24;
|
||||
|
||||
src <<= 8;
|
||||
if (b) {
|
||||
if (size < sizeof "255.")
|
||||
goto emsgsize;
|
||||
tp = dst;
|
||||
dst += SPRINTF((dst, "%u", b));
|
||||
if (src != 0L) {
|
||||
*dst++ = '.';
|
||||
*dst = '\0';
|
||||
}
|
||||
size -= (size_t)(dst - tp);
|
||||
}
|
||||
}
|
||||
if (dst == odst) {
|
||||
if (size < sizeof "0.0.0.0")
|
||||
goto emsgsize;
|
||||
strcpy(dst, "0.0.0.0");
|
||||
}
|
||||
return (odst);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* Return the network number from an internet
|
||||
* address; handles class a/b/c network #'s.
|
||||
*/
|
||||
u_long
|
||||
inet_netof(in)
|
||||
struct in_addr in;
|
||||
{
|
||||
register u_long i = ntohl(in.s_addr);
|
||||
|
||||
if (IN_CLASSA(i))
|
||||
return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
|
||||
else if (IN_CLASSB(i))
|
||||
return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
|
||||
else
|
||||
return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* Internet network address interpretation routine.
|
||||
* The library routines call this routine to interpret
|
||||
* network numbers.
|
||||
*/
|
||||
u_long
|
||||
inet_network(cp)
|
||||
register const char *cp;
|
||||
{
|
||||
register u_long val, base, n, i;
|
||||
register char c;
|
||||
u_long parts[4], *pp = parts;
|
||||
int digit;
|
||||
|
||||
again:
|
||||
val = 0; base = 10; digit = 0;
|
||||
if (*cp == '0')
|
||||
digit = 1, base = 8, cp++;
|
||||
if (*cp == 'x' || *cp == 'X')
|
||||
base = 16, cp++;
|
||||
while ((c = *cp) != 0) {
|
||||
if (isdigit((unsigned char)c)) {
|
||||
if (base == 8U && (c == '8' || c == '9'))
|
||||
return (INADDR_NONE);
|
||||
val = (val * base) + (c - '0');
|
||||
cp++;
|
||||
digit = 1;
|
||||
continue;
|
||||
}
|
||||
if (base == 16U && isxdigit((unsigned char)c)) {
|
||||
val = (val << 4) +
|
||||
(c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
|
||||
cp++;
|
||||
digit = 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!digit)
|
||||
return (INADDR_NONE);
|
||||
if (*cp == '.') {
|
||||
if (pp >= parts + 4 || val > 0xffU)
|
||||
return (INADDR_NONE);
|
||||
*pp++ = val, cp++;
|
||||
goto again;
|
||||
}
|
||||
if (*cp && !isspace(*cp&0xff))
|
||||
return (INADDR_NONE);
|
||||
*pp++ = val;
|
||||
n = pp - parts;
|
||||
if (n > 4U)
|
||||
return (INADDR_NONE);
|
||||
for (val = 0, i = 0; i < n; i++) {
|
||||
val <<= 8;
|
||||
val |= parts[i] & 0xff;
|
||||
}
|
||||
return (val);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* Convert network-format internet address
|
||||
* to base 256 d.d.d.d representation.
|
||||
*/
|
||||
/*const*/ char *
|
||||
inet_ntoa(struct in_addr in) {
|
||||
static char ret[18];
|
||||
|
||||
strcpy(ret, "[inet_ntoa error]");
|
||||
(void) inet_ntop(AF_INET, &in, ret, sizeof ret);
|
||||
return (ret);
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) ((size_t)sprintf x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size));
|
||||
static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size));
|
||||
|
||||
/* char *
|
||||
* inet_ntop(af, src, dst, size)
|
||||
* convert a network format address to presentation format.
|
||||
* return:
|
||||
* pointer to presentation format address (`dst'), or NULL (see errno).
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
const char *
|
||||
inet_ntop(af, src, dst, size)
|
||||
int af;
|
||||
const void *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_ntop4(src, dst, size));
|
||||
case AF_INET6:
|
||||
return (inet_ntop6(src, dst, size));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* const char *
|
||||
* inet_ntop4(src, dst, size)
|
||||
* format an IPv4 address
|
||||
* return:
|
||||
* `dst' (as a const)
|
||||
* notes:
|
||||
* (1) uses no statics
|
||||
* (2) takes a u_char* not an in_addr as input
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static const char *
|
||||
inet_ntop4(src, dst, size)
|
||||
const u_char *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
static const char fmt[] = "%u.%u.%u.%u";
|
||||
char tmp[sizeof "255.255.255.255"];
|
||||
|
||||
if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) {
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
||||
|
||||
/* const char *
|
||||
* inet_ntop6(src, dst, size)
|
||||
* convert IPv6 binary address into presentation (printable) format
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static const char *
|
||||
inet_ntop6(src, dst, size)
|
||||
const u_char *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
/*
|
||||
* Note that int32_t and int16_t need only be "at least" large enough
|
||||
* to contain a value of the specified size. On some systems, like
|
||||
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||
* Keep this in mind if you think this function should have been coded
|
||||
* to use pointer overlays. All the world's not a VAX.
|
||||
*/
|
||||
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
|
||||
struct { int base, len; } best, cur;
|
||||
u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Preprocess:
|
||||
* Copy the input (bytewise) array into a wordwise array.
|
||||
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||
*/
|
||||
memset(words, '\0', sizeof words);
|
||||
for (i = 0; i < NS_IN6ADDRSZ; i++)
|
||||
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
best.base = -1;
|
||||
cur.base = -1;
|
||||
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
|
||||
if (words[i] == 0) {
|
||||
if (cur.base == -1)
|
||||
cur.base = i, cur.len = 1;
|
||||
else
|
||||
cur.len++;
|
||||
} else {
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
cur.base = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
}
|
||||
if (best.base != -1 && best.len < 2)
|
||||
best.base = -1;
|
||||
|
||||
/*
|
||||
* Format the result.
|
||||
*/
|
||||
tp = tmp;
|
||||
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
|
||||
/* Are we inside the best run of 0x00's? */
|
||||
if (best.base != -1 && i >= best.base &&
|
||||
i < (best.base + best.len)) {
|
||||
if (i == best.base)
|
||||
*tp++ = ':';
|
||||
continue;
|
||||
}
|
||||
/* Are we following an initial run of 0x00s or any real hex? */
|
||||
if (i != 0)
|
||||
*tp++ = ':';
|
||||
/* Is this address an encapsulated IPv4? */
|
||||
if (i == 6 && best.base == 0 && (best.len == 6 ||
|
||||
(best.len == 7 && words[7] != 0x0001) ||
|
||||
(best.len == 5 && words[5] == 0xffff))) {
|
||||
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
|
||||
return (NULL);
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += SPRINTF((tp, "%x", words[i]));
|
||||
}
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) ==
|
||||
(NS_IN6ADDRSZ / NS_INT16SZ))
|
||||
*tp++ = ':';
|
||||
*tp++ = '\0';
|
||||
|
||||
/*
|
||||
* Check for overflow, copy, and we're done.
|
||||
*/
|
||||
if ((size_t)(tp - tmp) > size) {
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static int inet_pton4 __P((const char *src, u_char *dst));
|
||||
static int inet_pton6 __P((const char *src, u_char *dst));
|
||||
|
||||
/* int
|
||||
* inet_pton(af, src, dst)
|
||||
* convert from presentation format (which usually means ASCII printable)
|
||||
* to network format (which is usually some kind of binary format).
|
||||
* return:
|
||||
* 1 if the address was valid for the specified address family
|
||||
* 0 if the address wasn't valid (`dst' is untouched in this case)
|
||||
* -1 if some other error occurred (`dst' is untouched in this case, too)
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
int
|
||||
inet_pton(af, src, dst)
|
||||
int af;
|
||||
const char *src;
|
||||
void *dst;
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_pton4(src, dst));
|
||||
case AF_INET6:
|
||||
return (inet_pton6(src, dst));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton4(src, dst)
|
||||
* like inet_aton() but without all the hexadecimal and shorthand.
|
||||
* return:
|
||||
* 1 if `src' is a valid dotted quad, else 0.
|
||||
* notice:
|
||||
* does not touch `dst' unless it's returning 1.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton4(src, dst)
|
||||
const char *src;
|
||||
u_char *dst;
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
u_char tmp[NS_INADDRSZ], *tp;
|
||||
|
||||
saw_digit = 0;
|
||||
octets = 0;
|
||||
*(tp = tmp) = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr(digits, ch)) != NULL) {
|
||||
u_int new = *tp * 10 + (pch - digits);
|
||||
|
||||
if (saw_digit && *tp == 0)
|
||||
return (0);
|
||||
if (new > 255)
|
||||
return (0);
|
||||
*tp = new;
|
||||
if (!saw_digit) {
|
||||
if (++octets > 4)
|
||||
return (0);
|
||||
saw_digit = 1;
|
||||
}
|
||||
} else if (ch == '.' && saw_digit) {
|
||||
if (octets == 4)
|
||||
return (0);
|
||||
*++tp = 0;
|
||||
saw_digit = 0;
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
if (octets < 4)
|
||||
return (0);
|
||||
memcpy(dst, tmp, NS_INADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton6(src, dst)
|
||||
* convert presentation level address to network order binary form.
|
||||
* return:
|
||||
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
|
||||
* notice:
|
||||
* (1) does not touch `dst' unless it's returning 1.
|
||||
* (2) :: in a full address is silently ignored.
|
||||
* credit:
|
||||
* inspired by Mark Andrews.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton6(src, dst)
|
||||
const char *src;
|
||||
u_char *dst;
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *xdigits, *curtok;
|
||||
int ch, saw_xdigit;
|
||||
u_int val;
|
||||
|
||||
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
|
||||
endp = tp + NS_IN6ADDRSZ;
|
||||
colonp = NULL;
|
||||
/* Leading :: requires some special handling. */
|
||||
if (*src == ':')
|
||||
if (*++src != ':')
|
||||
return (0);
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if (pch != NULL) {
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':') {
|
||||
curtok = src;
|
||||
if (!saw_xdigit) {
|
||||
if (colonp)
|
||||
return (0);
|
||||
colonp = tp;
|
||||
continue;
|
||||
} else if (*src == '\0') {
|
||||
return (0);
|
||||
}
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
|
||||
inet_pton4(curtok, tp) > 0) {
|
||||
tp += NS_INADDRSZ;
|
||||
saw_xdigit = 0;
|
||||
break; /* '\0' was seen by inet_pton4(). */
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
if (saw_xdigit) {
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
}
|
||||
if (colonp != NULL) {
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
const int n = tp - colonp;
|
||||
int i;
|
||||
|
||||
if (tp == endp)
|
||||
return (0);
|
||||
for (i = 1; i <= n; i++) {
|
||||
endp[- i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
if (tp != endp)
|
||||
return (0);
|
||||
memcpy(dst, tmp, NS_IN6ADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
static char
|
||||
xtob(int c) {
|
||||
return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
|
||||
}
|
||||
|
||||
u_int
|
||||
inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) {
|
||||
u_char c, nib;
|
||||
u_int len = 0;
|
||||
|
||||
if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X'))
|
||||
return (0);
|
||||
ascii += 2;
|
||||
|
||||
while ((c = *ascii++) != '\0' && len < (u_int)maxlen) {
|
||||
if (c == '.' || c == '+' || c == '/')
|
||||
continue;
|
||||
if (!isascii(c))
|
||||
return (0);
|
||||
if (islower(c))
|
||||
c = toupper(c);
|
||||
if (isxdigit(c)) {
|
||||
nib = xtob(c);
|
||||
c = *ascii++;
|
||||
if (c != '\0') {
|
||||
c = toupper(c);
|
||||
if (isxdigit(c)) {
|
||||
*binary++ = (nib << 4) | xtob(c);
|
||||
len++;
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
return (len);
|
||||
}
|
||||
|
||||
char *
|
||||
inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) {
|
||||
int nib;
|
||||
int i;
|
||||
static char tmpbuf[2+255*3];
|
||||
char *start;
|
||||
|
||||
if (ascii)
|
||||
start = ascii;
|
||||
else {
|
||||
ascii = tmpbuf;
|
||||
start = tmpbuf;
|
||||
}
|
||||
|
||||
*ascii++ = '0';
|
||||
*ascii++ = 'x';
|
||||
|
||||
if (binlen > 255)
|
||||
binlen = 255;
|
||||
|
||||
for (i = 0; i < binlen; i++) {
|
||||
nib = *binary >> 4;
|
||||
*ascii++ = nib + (nib < 10 ? '0' : '7');
|
||||
nib = *binary++ & 0x0f;
|
||||
*ascii++ = nib + (nib < 10 ? '0' : '7');
|
||||
if (((i % 2) == 0 && (i + 1) < binlen))
|
||||
*ascii++ = '.';
|
||||
}
|
||||
*ascii = '\0';
|
||||
return (start);
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dns.c --- this is the top-level accessor function for the dns
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <resolv.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "hesiod.h"
|
||||
#include "dns_p.h"
|
||||
|
||||
/* forward */
|
||||
|
||||
static void dns_close(struct irs_acc *);
|
||||
static struct __res_state * dns_res_get(struct irs_acc *);
|
||||
static void dns_res_set(struct irs_acc *, struct __res_state *,
|
||||
void (*)(void *));
|
||||
|
||||
/* public */
|
||||
|
||||
struct irs_acc *
|
||||
irs_dns_acc(const char *options) {
|
||||
struct irs_acc *acc;
|
||||
struct dns_p *dns;
|
||||
|
||||
UNUSED(options);
|
||||
|
||||
if (!(acc = memget(sizeof *acc))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(acc, 0x5e, sizeof *acc);
|
||||
if (!(dns = memget(sizeof *dns))) {
|
||||
errno = ENOMEM;
|
||||
memput(acc, sizeof *acc);
|
||||
return (NULL);
|
||||
}
|
||||
memset(dns, 0x5e, sizeof *dns);
|
||||
dns->res = NULL;
|
||||
dns->free_res = NULL;
|
||||
if (hesiod_init(&dns->hes_ctx) < 0) {
|
||||
/*
|
||||
* We allow the dns accessor class to initialize
|
||||
* despite hesiod failing to initialize correctly,
|
||||
* since dns host queries don't depend on hesiod.
|
||||
*/
|
||||
dns->hes_ctx = NULL;
|
||||
}
|
||||
acc->private = dns;
|
||||
#ifdef WANT_IRS_GR
|
||||
acc->gr_map = irs_dns_gr;
|
||||
#else
|
||||
acc->gr_map = NULL;
|
||||
#endif
|
||||
#ifdef WANT_IRS_PW
|
||||
acc->pw_map = irs_dns_pw;
|
||||
#else
|
||||
acc->pw_map = NULL;
|
||||
#endif
|
||||
acc->sv_map = irs_dns_sv;
|
||||
acc->pr_map = irs_dns_pr;
|
||||
acc->ho_map = irs_dns_ho;
|
||||
acc->nw_map = irs_dns_nw;
|
||||
acc->ng_map = irs_nul_ng;
|
||||
acc->res_get = dns_res_get;
|
||||
acc->res_set = dns_res_set;
|
||||
acc->close = dns_close;
|
||||
return (acc);
|
||||
}
|
||||
|
||||
/* methods */
|
||||
static struct __res_state *
|
||||
dns_res_get(struct irs_acc *this) {
|
||||
struct dns_p *dns = (struct dns_p *)this->private;
|
||||
|
||||
if (dns->res == NULL) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
memset(dns->res, 0, sizeof *dns->res);
|
||||
dns_res_set(this, res, free);
|
||||
}
|
||||
|
||||
if ((dns->res->options & RES_INIT) == 0U &&
|
||||
res_ninit(dns->res) < 0)
|
||||
return (NULL);
|
||||
|
||||
return (dns->res);
|
||||
}
|
||||
|
||||
static void
|
||||
dns_res_set(struct irs_acc *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct dns_p *dns = (struct dns_p *)this->private;
|
||||
|
||||
if (dns->res && dns->free_res) {
|
||||
res_nclose(dns->res);
|
||||
(*dns->free_res)(dns->res);
|
||||
}
|
||||
dns->res = res;
|
||||
dns->free_res = free_res;
|
||||
}
|
||||
|
||||
static void
|
||||
dns_close(struct irs_acc *this) {
|
||||
struct dns_p *dns;
|
||||
|
||||
dns = (struct dns_p *)this->private;
|
||||
if (dns->res && dns->free_res)
|
||||
(*dns->free_res)(dns->res);
|
||||
if (dns->hes_ctx)
|
||||
hesiod_end(dns->hes_ctx);
|
||||
memput(dns, sizeof *dns);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,589 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* Imports. */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "dns_p.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) sprintf x
|
||||
#endif
|
||||
|
||||
/* Definitions. */
|
||||
|
||||
#define MAXALIASES 35
|
||||
|
||||
#define MAXPACKET (64*1024)
|
||||
|
||||
struct pvt {
|
||||
struct nwent net;
|
||||
char * ali[MAXALIASES];
|
||||
char buf[BUFSIZ+1];
|
||||
struct __res_state * res;
|
||||
void (*free_res)(void *);
|
||||
};
|
||||
|
||||
typedef union {
|
||||
long al;
|
||||
char ac;
|
||||
} align;
|
||||
|
||||
enum by_what { by_addr, by_name };
|
||||
|
||||
/* Forwards. */
|
||||
|
||||
static void nw_close(struct irs_nw *);
|
||||
static struct nwent * nw_byname(struct irs_nw *, const char *, int);
|
||||
static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int);
|
||||
static struct nwent * nw_next(struct irs_nw *);
|
||||
static void nw_rewind(struct irs_nw *);
|
||||
static void nw_minimize(struct irs_nw *);
|
||||
static struct __res_state * nw_res_get(struct irs_nw *this);
|
||||
static void nw_res_set(struct irs_nw *this,
|
||||
struct __res_state *res,
|
||||
void (*free_res)(void *));
|
||||
|
||||
static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int);
|
||||
static struct nwent * get1101byname(struct irs_nw *, const char *);
|
||||
static struct nwent * get1101answer(struct irs_nw *,
|
||||
u_char *ansbuf, int anslen,
|
||||
enum by_what by_what,
|
||||
int af, const char *name,
|
||||
const u_char *addr, int addrlen);
|
||||
static struct nwent * get1101mask(struct irs_nw *this, struct nwent *);
|
||||
static int make1101inaddr(const u_char *, int, char *, int);
|
||||
static void normalize_name(char *name);
|
||||
static int init(struct irs_nw *this);
|
||||
|
||||
/* Exports. */
|
||||
|
||||
struct irs_nw *
|
||||
irs_dns_nw(struct irs_acc *this) {
|
||||
struct irs_nw *nw;
|
||||
struct pvt *pvt;
|
||||
|
||||
UNUSED(this);
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
if (!(nw = memget(sizeof *nw))) {
|
||||
memput(pvt, sizeof *pvt);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(nw, 0x5e, sizeof *nw);
|
||||
nw->private = pvt;
|
||||
nw->close = nw_close;
|
||||
nw->byname = nw_byname;
|
||||
nw->byaddr = nw_byaddr;
|
||||
nw->next = nw_next;
|
||||
nw->rewind = nw_rewind;
|
||||
nw->minimize = nw_minimize;
|
||||
nw->res_get = nw_res_get;
|
||||
nw->res_set = nw_res_set;
|
||||
return (nw);
|
||||
}
|
||||
|
||||
/* Methods. */
|
||||
|
||||
static void
|
||||
nw_close(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
nw_minimize(this);
|
||||
|
||||
if (pvt->res && pvt->free_res)
|
||||
(*pvt->free_res)(pvt->res);
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_byname(struct irs_nw *this, const char *name, int af) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (get1101byname(this, name));
|
||||
default:
|
||||
(void)NULL;
|
||||
}
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_byaddr(struct irs_nw *this, void *net, int len, int af) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (get1101byaddr(this, net, len));
|
||||
default:
|
||||
(void)NULL;
|
||||
}
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_next(struct irs_nw *this) {
|
||||
|
||||
UNUSED(this);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
nw_rewind(struct irs_nw *this) {
|
||||
UNUSED(this);
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
static void
|
||||
nw_minimize(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->res)
|
||||
res_nclose(pvt->res);
|
||||
}
|
||||
|
||||
static struct __res_state *
|
||||
nw_res_get(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (!res) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof *res);
|
||||
nw_res_set(this, res, free);
|
||||
}
|
||||
|
||||
return (pvt->res);
|
||||
}
|
||||
|
||||
static void
|
||||
nw_res_set(struct irs_nw *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->res && pvt->free_res) {
|
||||
res_nclose(pvt->res);
|
||||
(*pvt->free_res)(pvt->res);
|
||||
}
|
||||
|
||||
pvt->res = res;
|
||||
pvt->free_res = free_res;
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
static struct nwent *
|
||||
get1101byname(struct irs_nw *this, const char *name) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
u_char *ansbuf;
|
||||
int anslen;
|
||||
struct nwent *result;
|
||||
|
||||
ansbuf = memget(MAXPACKET);
|
||||
if (ansbuf == NULL) {
|
||||
errno = ENOMEM;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, ansbuf, MAXPACKET);
|
||||
if (anslen < 0) {
|
||||
memput(ansbuf, MAXPACKET);
|
||||
return (NULL);
|
||||
}
|
||||
result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_name,
|
||||
AF_INET, name, NULL, 0));
|
||||
memput(ansbuf, MAXPACKET);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
get1101byaddr(struct irs_nw *this, u_char *net, int len) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char qbuf[sizeof "255.255.255.255.in-addr.arpa"];
|
||||
struct nwent *result;
|
||||
u_char *ansbuf;
|
||||
int anslen;
|
||||
|
||||
if (len < 1 || len > 32) {
|
||||
errno = EINVAL;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0)
|
||||
return (NULL);
|
||||
ansbuf = memget(MAXPACKET);
|
||||
if (ansbuf == NULL) {
|
||||
errno = ENOMEM;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, ansbuf, MAXPACKET);
|
||||
if (anslen < 0) {
|
||||
memput(ansbuf, MAXPACKET);
|
||||
return (NULL);
|
||||
}
|
||||
result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr,
|
||||
AF_INET, NULL, net, len));
|
||||
memput(ansbuf, MAXPACKET);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
get1101answer(struct irs_nw *this,
|
||||
u_char *ansbuf, int anslen, enum by_what by_what,
|
||||
int af, const char *name, const u_char *addr, int addrlen)
|
||||
{
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
int type, class, ancount, qdcount, haveanswer;
|
||||
char *bp, *ep, **ap;
|
||||
u_char *cp, *eom;
|
||||
HEADER *hp;
|
||||
|
||||
/* Initialize, and parse header. */
|
||||
eom = ansbuf + anslen;
|
||||
if (ansbuf + HFIXEDSZ > eom) {
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
|
||||
return (NULL);
|
||||
}
|
||||
hp = (HEADER *)ansbuf;
|
||||
cp = ansbuf + HFIXEDSZ;
|
||||
qdcount = ntohs(hp->qdcount);
|
||||
while (qdcount-- > 0) {
|
||||
int n = dn_skipname(cp, eom);
|
||||
cp += n + QFIXEDSZ;
|
||||
if (n < 0 || cp > eom) {
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
ancount = ntohs(hp->ancount);
|
||||
if (!ancount) {
|
||||
if (hp->aa)
|
||||
RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
|
||||
else
|
||||
RES_SET_H_ERRNO(pvt->res, TRY_AGAIN);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Prepare a return structure. */
|
||||
bp = pvt->buf;
|
||||
ep = pvt->buf + sizeof(pvt->buf);
|
||||
pvt->net.n_name = NULL;
|
||||
pvt->net.n_aliases = pvt->ali;
|
||||
pvt->net.n_addrtype = af;
|
||||
pvt->net.n_addr = NULL;
|
||||
pvt->net.n_length = addrlen;
|
||||
|
||||
/* Save input key if given. */
|
||||
switch (by_what) {
|
||||
case by_name:
|
||||
if (name != NULL) {
|
||||
int n = strlen(name) + 1;
|
||||
|
||||
if (n > (ep - bp)) {
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
|
||||
return (NULL);
|
||||
}
|
||||
pvt->net.n_name = strcpy(bp, name); /* (checked) */
|
||||
bp += n;
|
||||
}
|
||||
break;
|
||||
case by_addr:
|
||||
if (addr != NULL && addrlen != 0) {
|
||||
int n = addrlen / 8 + ((addrlen % 8) != 0);
|
||||
|
||||
if (INADDRSZ > (ep - bp)) {
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
|
||||
return (NULL);
|
||||
}
|
||||
memset(bp, 0, INADDRSZ);
|
||||
memcpy(bp, addr, n);
|
||||
pvt->net.n_addr = bp;
|
||||
bp += INADDRSZ;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Parse the answer, collect aliases. */
|
||||
ap = pvt->ali;
|
||||
haveanswer = 0;
|
||||
while (--ancount >= 0 && cp < eom) {
|
||||
int n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
|
||||
|
||||
cp += n; /* Owner */
|
||||
if (n < 0 || !maybe_dnok(pvt->res, bp) ||
|
||||
cp + 3 * INT16SZ + INT32SZ > eom) {
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
|
||||
return (NULL);
|
||||
}
|
||||
GETSHORT(type, cp); /* Type */
|
||||
GETSHORT(class, cp); /* Class */
|
||||
cp += INT32SZ; /* TTL */
|
||||
GETSHORT(n, cp); /* RDLENGTH */
|
||||
if (class == C_IN && type == T_PTR) {
|
||||
int nn;
|
||||
|
||||
nn = dn_expand(ansbuf, eom, cp, bp, ep - bp);
|
||||
if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) {
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
|
||||
return (NULL);
|
||||
}
|
||||
normalize_name(bp);
|
||||
switch (by_what) {
|
||||
case by_addr: {
|
||||
if (pvt->net.n_name == NULL)
|
||||
pvt->net.n_name = bp;
|
||||
else if (ns_samename(pvt->net.n_name, bp) == 1)
|
||||
break;
|
||||
else
|
||||
*ap++ = bp;
|
||||
nn = strlen(bp) + 1;
|
||||
bp += nn;
|
||||
haveanswer++;
|
||||
break;
|
||||
}
|
||||
case by_name: {
|
||||
u_int b1, b2, b3, b4;
|
||||
|
||||
if (pvt->net.n_addr != NULL ||
|
||||
sscanf(bp, "%u.%u.%u.%u.in-addr.arpa",
|
||||
&b1, &b2, &b3, &b4) != 4)
|
||||
break;
|
||||
if ((ep - bp) < INADDRSZ) {
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
|
||||
return (NULL);
|
||||
}
|
||||
pvt->net.n_addr = bp;
|
||||
*bp++ = b4;
|
||||
*bp++ = b3;
|
||||
*bp++ = b2;
|
||||
*bp++ = b1;
|
||||
pvt->net.n_length = INADDRSZ * 8;
|
||||
haveanswer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
cp += n; /* RDATA */
|
||||
}
|
||||
if (!haveanswer) {
|
||||
RES_SET_H_ERRNO(pvt->res, TRY_AGAIN);
|
||||
return (NULL);
|
||||
}
|
||||
*ap = NULL;
|
||||
|
||||
return (&pvt->net);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
get1101mask(struct irs_nw *this, struct nwent *nwent) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME];
|
||||
int anslen, type, class, ancount, qdcount;
|
||||
u_char *ansbuf, *cp, *eom;
|
||||
HEADER *hp;
|
||||
|
||||
if (!nwent)
|
||||
return (NULL);
|
||||
if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf)
|
||||
< 0) {
|
||||
/* "First, do no harm." */
|
||||
return (nwent);
|
||||
}
|
||||
|
||||
ansbuf = memget(MAXPACKET);
|
||||
if (ansbuf == NULL) {
|
||||
errno = ENOMEM;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
/* Query for the A RR that would hold this network's mask. */
|
||||
anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, MAXPACKET);
|
||||
if (anslen < HFIXEDSZ) {
|
||||
memput(ansbuf, MAXPACKET);
|
||||
return (nwent);
|
||||
}
|
||||
|
||||
/* Initialize, and parse header. */
|
||||
hp = (HEADER *)ansbuf;
|
||||
cp = ansbuf + HFIXEDSZ;
|
||||
eom = ansbuf + anslen;
|
||||
qdcount = ntohs(hp->qdcount);
|
||||
while (qdcount-- > 0) {
|
||||
int n = dn_skipname(cp, eom);
|
||||
cp += n + QFIXEDSZ;
|
||||
if (n < 0 || cp > eom) {
|
||||
memput(ansbuf, MAXPACKET);
|
||||
return (nwent);
|
||||
}
|
||||
}
|
||||
ancount = ntohs(hp->ancount);
|
||||
|
||||
/* Parse the answer, collect aliases. */
|
||||
while (--ancount >= 0 && cp < eom) {
|
||||
int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner);
|
||||
|
||||
if (n < 0 || !maybe_dnok(pvt->res, owner))
|
||||
break;
|
||||
cp += n; /* Owner */
|
||||
if (cp + 3 * INT16SZ + INT32SZ > eom)
|
||||
break;
|
||||
GETSHORT(type, cp); /* Type */
|
||||
GETSHORT(class, cp); /* Class */
|
||||
cp += INT32SZ; /* TTL */
|
||||
GETSHORT(n, cp); /* RDLENGTH */
|
||||
if (cp + n > eom)
|
||||
break;
|
||||
if (n == INADDRSZ && class == C_IN && type == T_A &&
|
||||
ns_samename(qbuf, owner) == 1) {
|
||||
/* This A RR indicates the actual netmask. */
|
||||
int nn, mm;
|
||||
|
||||
nwent->n_length = 0;
|
||||
for (nn = 0; nn < INADDRSZ; nn++)
|
||||
for (mm = 7; mm >= 0; mm--)
|
||||
if (cp[nn] & (1 << mm))
|
||||
nwent->n_length++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
cp += n; /* RDATA */
|
||||
}
|
||||
memput(ansbuf, MAXPACKET);
|
||||
return (nwent);
|
||||
}
|
||||
|
||||
static int
|
||||
make1101inaddr(const u_char *net, int bits, char *name, int size) {
|
||||
int n, m;
|
||||
char *ep;
|
||||
|
||||
ep = name + size;
|
||||
|
||||
/* Zero fill any whole bytes left out of the prefix. */
|
||||
for (n = (32 - bits) / 8; n > 0; n--) {
|
||||
if (ep - name < (int)(sizeof "0."))
|
||||
goto emsgsize;
|
||||
m = SPRINTF((name, "0."));
|
||||
name += m;
|
||||
}
|
||||
|
||||
/* Format the partial byte, if any, within the prefix. */
|
||||
if ((n = bits % 8) != 0) {
|
||||
if (ep - name < (int)(sizeof "255."))
|
||||
goto emsgsize;
|
||||
m = SPRINTF((name, "%u.",
|
||||
net[bits / 8] & ~((1 << (8 - n)) - 1)));
|
||||
name += m;
|
||||
}
|
||||
|
||||
/* Format the whole bytes within the prefix. */
|
||||
for (n = bits / 8; n > 0; n--) {
|
||||
if (ep - name < (int)(sizeof "255."))
|
||||
goto emsgsize;
|
||||
m = SPRINTF((name, "%u.", net[n - 1]));
|
||||
name += m;
|
||||
}
|
||||
|
||||
/* Add the static text. */
|
||||
if (ep - name < (int)(sizeof "in-addr.arpa"))
|
||||
goto emsgsize;
|
||||
(void) SPRINTF((name, "in-addr.arpa"));
|
||||
return (0);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static void
|
||||
normalize_name(char *name) {
|
||||
char *t;
|
||||
|
||||
/* Make lower case. */
|
||||
for (t = name; *t; t++)
|
||||
if (isascii((unsigned char)*t) && isupper((unsigned char)*t))
|
||||
*t = tolower((*t)&0xff);
|
||||
|
||||
/* Remove trailing dots. */
|
||||
while (t > name && t[-1] == '.')
|
||||
*--t = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
init(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res && !nw_res_get(this))
|
||||
return (-1);
|
||||
if (((pvt->res->options & RES_INIT) == 0U) &&
|
||||
res_ninit(pvt->res) == -1)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _DNS_P_H_INCLUDED
|
||||
#define _DNS_P_H_INCLUDED
|
||||
|
||||
#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
|
||||
(ok)(nm) != 0)
|
||||
#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
|
||||
#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
|
||||
|
||||
/*
|
||||
* Object state.
|
||||
*/
|
||||
struct dns_p {
|
||||
void *hes_ctx;
|
||||
struct __res_state *res;
|
||||
void (*free_res) __P((void *));
|
||||
};
|
||||
|
||||
/*
|
||||
* Methods.
|
||||
*/
|
||||
|
||||
extern struct irs_gr * irs_dns_gr __P((struct irs_acc *));
|
||||
extern struct irs_pw * irs_dns_pw __P((struct irs_acc *));
|
||||
extern struct irs_sv * irs_dns_sv __P((struct irs_acc *));
|
||||
extern struct irs_pr * irs_dns_pr __P((struct irs_acc *));
|
||||
extern struct irs_ho * irs_dns_ho __P((struct irs_acc *));
|
||||
extern struct irs_nw * irs_dns_nw __P((struct irs_acc *));
|
||||
|
||||
#endif /*_DNS_P_H_INCLUDED*/
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "hesiod.h"
|
||||
#include "dns_p.h"
|
||||
|
||||
/* Types. */
|
||||
|
||||
struct pvt {
|
||||
struct dns_p * dns;
|
||||
struct protoent proto;
|
||||
char * prbuf;
|
||||
};
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void pr_close(struct irs_pr *);
|
||||
static struct protoent * pr_byname(struct irs_pr *, const char *);
|
||||
static struct protoent * pr_bynumber(struct irs_pr *, int);
|
||||
static struct protoent * pr_next(struct irs_pr *);
|
||||
static void pr_rewind(struct irs_pr *);
|
||||
static void pr_minimize(struct irs_pr *);
|
||||
static struct __res_state * pr_res_get(struct irs_pr *);
|
||||
static void pr_res_set(struct irs_pr *,
|
||||
struct __res_state *,
|
||||
void (*)(void *));
|
||||
|
||||
static struct protoent * parse_hes_list(struct irs_pr *, char **);
|
||||
|
||||
/* Public. */
|
||||
|
||||
struct irs_pr *
|
||||
irs_dns_pr(struct irs_acc *this) {
|
||||
struct dns_p *dns = (struct dns_p *)this->private;
|
||||
struct pvt *pvt;
|
||||
struct irs_pr *pr;
|
||||
|
||||
if (!dns->hes_ctx) {
|
||||
errno = ENODEV;
|
||||
return (NULL);
|
||||
}
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
if (!(pr = memget(sizeof *pr))) {
|
||||
memput(pvt, sizeof *pvt);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pr, 0x5e, sizeof *pr);
|
||||
pvt->dns = dns;
|
||||
pr->private = pvt;
|
||||
pr->byname = pr_byname;
|
||||
pr->bynumber = pr_bynumber;
|
||||
pr->next = pr_next;
|
||||
pr->rewind = pr_rewind;
|
||||
pr->close = pr_close;
|
||||
pr->minimize = pr_minimize;
|
||||
pr->res_get = pr_res_get;
|
||||
pr->res_set = pr_res_set;
|
||||
return (pr);
|
||||
}
|
||||
|
||||
/* Methods. */
|
||||
|
||||
static void
|
||||
pr_close(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->proto.p_aliases)
|
||||
free(pvt->proto.p_aliases);
|
||||
if (pvt->prbuf)
|
||||
free(pvt->prbuf);
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_byname(struct irs_pr *this, const char *name) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct dns_p *dns = pvt->dns;
|
||||
struct protoent *proto;
|
||||
char **hes_list;
|
||||
|
||||
if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "protocol")))
|
||||
return (NULL);
|
||||
|
||||
proto = parse_hes_list(this, hes_list);
|
||||
hesiod_free_list(dns->hes_ctx, hes_list);
|
||||
return (proto);
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_bynumber(struct irs_pr *this, int num) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct dns_p *dns = pvt->dns;
|
||||
struct protoent *proto;
|
||||
char numstr[16];
|
||||
char **hes_list;
|
||||
|
||||
sprintf(numstr, "%d", num);
|
||||
if (!(hes_list = hesiod_resolve(dns->hes_ctx, numstr, "protonum")))
|
||||
return (NULL);
|
||||
|
||||
proto = parse_hes_list(this, hes_list);
|
||||
hesiod_free_list(dns->hes_ctx, hes_list);
|
||||
return (proto);
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_next(struct irs_pr *this) {
|
||||
UNUSED(this);
|
||||
errno = ENODEV;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_rewind(struct irs_pr *this) {
|
||||
UNUSED(this);
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
static void
|
||||
pr_minimize(struct irs_pr *this) {
|
||||
UNUSED(this);
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
static struct __res_state *
|
||||
pr_res_get(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct dns_p *dns = pvt->dns;
|
||||
|
||||
return (__hesiod_res_get(dns->hes_ctx));
|
||||
}
|
||||
|
||||
static void
|
||||
pr_res_set(struct irs_pr *this, struct __res_state * res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct dns_p *dns = pvt->dns;
|
||||
|
||||
__hesiod_res_set(dns->hes_ctx, res, free_res);
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
static struct protoent *
|
||||
parse_hes_list(struct irs_pr *this, char **hes_list) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char *p, *cp, **cpp, **new;
|
||||
int num = 0;
|
||||
int max = 0;
|
||||
|
||||
for (cpp = hes_list; *cpp; cpp++) {
|
||||
cp = *cpp;
|
||||
|
||||
/* Strip away comments, if any. */
|
||||
if ((p = strchr(cp, '#')))
|
||||
*p = 0;
|
||||
|
||||
/* Skip blank lines. */
|
||||
p = cp;
|
||||
while (*p && !isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (!*p)
|
||||
continue;
|
||||
|
||||
/* OK, we've got a live one. Let's parse it for real. */
|
||||
if (pvt->prbuf)
|
||||
free(pvt->prbuf);
|
||||
pvt->prbuf = strdup(cp);
|
||||
|
||||
p = pvt->prbuf;
|
||||
pvt->proto.p_name = p;
|
||||
while (*p && !isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (!*p)
|
||||
continue;
|
||||
*p++ = '\0';
|
||||
|
||||
pvt->proto.p_proto = atoi(p);
|
||||
while (*p && !isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (*p)
|
||||
*p++ = '\0';
|
||||
|
||||
while (*p) {
|
||||
if ((num + 1) >= max || !pvt->proto.p_aliases) {
|
||||
max += 10;
|
||||
new = realloc(pvt->proto.p_aliases,
|
||||
max * sizeof(char *));
|
||||
if (!new) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
pvt->proto.p_aliases = new;
|
||||
}
|
||||
pvt->proto.p_aliases[num++] = p;
|
||||
while (*p && !isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (*p)
|
||||
*p++ = '\0';
|
||||
}
|
||||
if (!pvt->proto.p_aliases)
|
||||
pvt->proto.p_aliases = malloc(sizeof(char *));
|
||||
if (!pvt->proto.p_aliases)
|
||||
goto cleanup;
|
||||
pvt->proto.p_aliases[num] = NULL;
|
||||
return (&pvt->proto);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (pvt->proto.p_aliases) {
|
||||
free(pvt->proto.p_aliases);
|
||||
pvt->proto.p_aliases = NULL;
|
||||
}
|
||||
if (pvt->prbuf) {
|
||||
free(pvt->prbuf);
|
||||
pvt->prbuf = NULL;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "hesiod.h"
|
||||
#include "dns_p.h"
|
||||
|
||||
/* Definitions */
|
||||
|
||||
struct pvt {
|
||||
struct dns_p * dns;
|
||||
struct servent serv;
|
||||
char * svbuf;
|
||||
struct __res_state * res;
|
||||
void (*free_res)(void *);
|
||||
};
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void sv_close(struct irs_sv *);
|
||||
static struct servent * sv_byname(struct irs_sv *,
|
||||
const char *, const char *);
|
||||
static struct servent * sv_byport(struct irs_sv *, int, const char *);
|
||||
static struct servent * sv_next(struct irs_sv *);
|
||||
static void sv_rewind(struct irs_sv *);
|
||||
static void sv_minimize(struct irs_sv *);
|
||||
#ifdef SV_RES_SETGET
|
||||
static struct __res_state * sv_res_get(struct irs_sv *);
|
||||
static void sv_res_set(struct irs_sv *,
|
||||
struct __res_state *,
|
||||
void (*)(void *));
|
||||
#endif
|
||||
|
||||
static struct servent * parse_hes_list(struct irs_sv *,
|
||||
char **, const char *);
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_sv *
|
||||
irs_dns_sv(struct irs_acc *this) {
|
||||
struct dns_p *dns = (struct dns_p *)this->private;
|
||||
struct irs_sv *sv;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!dns || !dns->hes_ctx) {
|
||||
errno = ENODEV;
|
||||
return (NULL);
|
||||
}
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pvt->dns = dns;
|
||||
if (!(sv = memget(sizeof *sv))) {
|
||||
memput(pvt, sizeof *pvt);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(sv, 0x5e, sizeof *sv);
|
||||
sv->private = pvt;
|
||||
sv->byname = sv_byname;
|
||||
sv->byport = sv_byport;
|
||||
sv->next = sv_next;
|
||||
sv->rewind = sv_rewind;
|
||||
sv->close = sv_close;
|
||||
sv->minimize = sv_minimize;
|
||||
#ifdef SV_RES_SETGET
|
||||
sv->res_get = sv_res_get;
|
||||
sv->res_set = sv_res_set;
|
||||
#else
|
||||
sv->res_get = NULL; /* sv_res_get; */
|
||||
sv->res_set = NULL; /* sv_res_set; */
|
||||
#endif
|
||||
return (sv);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
sv_close(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->serv.s_aliases)
|
||||
free(pvt->serv.s_aliases);
|
||||
if (pvt->svbuf)
|
||||
free(pvt->svbuf);
|
||||
|
||||
if (pvt->res && pvt->free_res)
|
||||
(*pvt->free_res)(pvt->res);
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_byname(struct irs_sv *this, const char *name, const char *proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct dns_p *dns = pvt->dns;
|
||||
struct servent *s;
|
||||
char **hes_list;
|
||||
|
||||
if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "service")))
|
||||
return (NULL);
|
||||
|
||||
s = parse_hes_list(this, hes_list, proto);
|
||||
hesiod_free_list(dns->hes_ctx, hes_list);
|
||||
return (s);
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_byport(struct irs_sv *this, int port, const char *proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct dns_p *dns = pvt->dns;
|
||||
struct servent *s;
|
||||
char portstr[16];
|
||||
char **hes_list;
|
||||
|
||||
sprintf(portstr, "%d", ntohs(port));
|
||||
if (!(hes_list = hesiod_resolve(dns->hes_ctx, portstr, "port")))
|
||||
return (NULL);
|
||||
|
||||
s = parse_hes_list(this, hes_list, proto);
|
||||
hesiod_free_list(dns->hes_ctx, hes_list);
|
||||
return (s);
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_next(struct irs_sv *this) {
|
||||
UNUSED(this);
|
||||
errno = ENODEV;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sv_rewind(struct irs_sv *this) {
|
||||
UNUSED(this);
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
static struct servent *
|
||||
parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char *p, *cp, **cpp, **new;
|
||||
int proto_len;
|
||||
int num = 0;
|
||||
int max = 0;
|
||||
|
||||
for (cpp = hes_list; *cpp; cpp++) {
|
||||
cp = *cpp;
|
||||
|
||||
/* Strip away comments, if any. */
|
||||
if ((p = strchr(cp, '#')))
|
||||
*p = 0;
|
||||
|
||||
/* Check to make sure the protocol matches. */
|
||||
p = cp;
|
||||
while (*p && !isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (!*p)
|
||||
continue;
|
||||
if (proto) {
|
||||
proto_len = strlen(proto);
|
||||
if (strncasecmp(++p, proto, proto_len) != 0)
|
||||
continue;
|
||||
if (p[proto_len] && !isspace(p[proto_len]&0xff))
|
||||
continue;
|
||||
}
|
||||
/* OK, we've got a live one. Let's parse it for real. */
|
||||
if (pvt->svbuf)
|
||||
free(pvt->svbuf);
|
||||
pvt->svbuf = strdup(cp);
|
||||
|
||||
p = pvt->svbuf;
|
||||
pvt->serv.s_name = p;
|
||||
while (*p && !isspace(*p&0xff))
|
||||
p++;
|
||||
if (!*p)
|
||||
continue;
|
||||
*p++ = '\0';
|
||||
|
||||
pvt->serv.s_proto = p;
|
||||
while (*p && !isspace(*p&0xff))
|
||||
p++;
|
||||
if (!*p)
|
||||
continue;
|
||||
*p++ = '\0';
|
||||
|
||||
pvt->serv.s_port = htons((u_short) atoi(p));
|
||||
while (*p && !isspace(*p&0xff))
|
||||
p++;
|
||||
if (*p)
|
||||
*p++ = '\0';
|
||||
|
||||
while (*p) {
|
||||
if ((num + 1) >= max || !pvt->serv.s_aliases) {
|
||||
max += 10;
|
||||
new = realloc(pvt->serv.s_aliases,
|
||||
max * sizeof(char *));
|
||||
if (!new) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
pvt->serv.s_aliases = new;
|
||||
}
|
||||
pvt->serv.s_aliases[num++] = p;
|
||||
while (*p && !isspace(*p&0xff))
|
||||
p++;
|
||||
if (*p)
|
||||
*p++ = '\0';
|
||||
}
|
||||
if (!pvt->serv.s_aliases)
|
||||
pvt->serv.s_aliases = malloc(sizeof(char *));
|
||||
if (!pvt->serv.s_aliases)
|
||||
goto cleanup;
|
||||
pvt->serv.s_aliases[num] = NULL;
|
||||
return (&pvt->serv);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (pvt->serv.s_aliases) {
|
||||
free(pvt->serv.s_aliases);
|
||||
pvt->serv.s_aliases = NULL;
|
||||
}
|
||||
if (pvt->svbuf) {
|
||||
free(pvt->svbuf);
|
||||
pvt->svbuf = NULL;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sv_minimize(struct irs_sv *this) {
|
||||
UNUSED(this);
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
#ifdef SV_RES_SETGET
|
||||
static struct __res_state *
|
||||
sv_res_get(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct dns_p *dns = pvt->dns;
|
||||
|
||||
return (__hesiod_res_get(dns->hes_ctx));
|
||||
}
|
||||
|
||||
static void
|
||||
sv_res_set(struct irs_sv *this, struct __res_state * res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct dns_p *dns = pvt->dns;
|
||||
|
||||
__hesiod_res_set(dns->hes_ctx, res, free_res);
|
||||
}
|
||||
#endif
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 2001 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <port_before.h>
|
||||
#include <netdb.h>
|
||||
#include <port_after.h>
|
||||
|
||||
#ifdef DO_PTHREADS
|
||||
#include <TLS.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
static const char *gai_errlist[] = {
|
||||
"no error",
|
||||
"address family not supported for name",/* EAI_ADDRFAMILY */
|
||||
"temporary failure", /* EAI_AGAIN */
|
||||
"invalid flags", /* EAI_BADFLAGS */
|
||||
"permanent failure", /* EAI_FAIL */
|
||||
"address family not supported", /* EAI_FAMILY */
|
||||
"memory failure", /* EAI_MEMORY */
|
||||
"no address", /* EAI_NODATA */
|
||||
"unknown name or service", /* EAI_NONAME */
|
||||
"service not supported for socktype", /* EAI_SERVICE */
|
||||
"socktype not supported", /* EAI_SOCKTYPE */
|
||||
"system failure", /* EAI_SYSTEM */
|
||||
"bad hints", /* EAI_BADHINTS */
|
||||
"bad protocol", /* EAI_PROTOCOL */
|
||||
|
||||
"unknown error" /* Must be last. */
|
||||
};
|
||||
|
||||
static const int gai_nerr = (sizeof(gai_errlist)/sizeof(*gai_errlist));
|
||||
|
||||
#define EAI_BUFSIZE 128
|
||||
|
||||
#ifdef DO_PTHREADS
|
||||
int32 gGaiStrerrorKey;
|
||||
#endif
|
||||
|
||||
const char *
|
||||
gai_strerror(int ecode) {
|
||||
#ifndef DO_PTHREADS
|
||||
static char buf[EAI_BUFSIZE];
|
||||
#else /* DO_PTHREADS */
|
||||
#ifndef LIBBIND_MUTEX_INITIALIZER
|
||||
#define LIBBIND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
#endif
|
||||
char *buf;
|
||||
#endif
|
||||
|
||||
if (ecode >= 0 && ecode < (gai_nerr - 1))
|
||||
return (gai_errlist[ecode]);
|
||||
|
||||
#ifdef DO_PTHREADS
|
||||
buf = tls_get(gGaiStrerrorKey);
|
||||
if (buf == NULL) {
|
||||
buf = malloc(EAI_BUFSIZE);
|
||||
if (buf == NULL)
|
||||
return ("unknown error");
|
||||
on_exit_thread(free, buf);
|
||||
tls_set(gGaiStrerrorKey, buf);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* XXX This really should be snprintf(buf, EAI_BUFSIZE, ...).
|
||||
* It is safe until message catalogs are used.
|
||||
*/
|
||||
sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode);
|
||||
return (buf);
|
||||
}
|
||||
@@ -1,432 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* this is the top level dispatcher
|
||||
*
|
||||
* The dispatcher is implemented as an accessor class; it is an
|
||||
* accessor class that calls other accessor classes, as controlled by a
|
||||
* configuration file.
|
||||
*
|
||||
* A big difference between this accessor class and others is that the
|
||||
* map class initializers are NULL, and the map classes are already
|
||||
* filled in with method functions that will do the right thing.
|
||||
*/
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "gen_p.h"
|
||||
|
||||
/* Definitions */
|
||||
|
||||
struct nameval {
|
||||
const char * name;
|
||||
int val;
|
||||
};
|
||||
|
||||
static const struct nameval acc_names[irs_nacc+1] = {
|
||||
{ "local", irs_lcl },
|
||||
{ "dns", irs_dns },
|
||||
{ "nis", irs_nis },
|
||||
{ "irp", irs_irp },
|
||||
{ NULL, irs_nacc }
|
||||
};
|
||||
|
||||
typedef struct irs_acc *(*accinit) __P((const char *options));
|
||||
|
||||
static const accinit accs[irs_nacc+1] = {
|
||||
irs_lcl_acc,
|
||||
irs_dns_acc,
|
||||
#ifdef WANT_IRS_NIS
|
||||
irs_nis_acc,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
irs_irp_acc,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct nameval map_names[irs_nmap+1] = {
|
||||
{ "group", irs_gr },
|
||||
{ "passwd", irs_pw },
|
||||
{ "services", irs_sv },
|
||||
{ "protocols", irs_pr },
|
||||
{ "hosts", irs_ho },
|
||||
{ "networks", irs_nw },
|
||||
{ "netgroup", irs_ng },
|
||||
{ NULL, irs_nmap }
|
||||
};
|
||||
|
||||
static const struct nameval option_names[] = {
|
||||
{ "merge", IRS_MERGE },
|
||||
{ "continue", IRS_CONTINUE },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void gen_close(struct irs_acc *);
|
||||
static struct __res_state * gen_res_get(struct irs_acc *);
|
||||
static void gen_res_set(struct irs_acc *, struct __res_state *,
|
||||
void (*)(void *));
|
||||
static int find_name(const char *, const struct nameval nv[]);
|
||||
static void init_map_rules(struct gen_p *, const char *conf_file);
|
||||
static struct irs_rule *release_rule(struct irs_rule *);
|
||||
static int add_rule(struct gen_p *,
|
||||
enum irs_map_id, enum irs_acc_id,
|
||||
const char *);
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_acc *
|
||||
irs_gen_acc(const char *options, const char *conf_file) {
|
||||
struct irs_acc *acc;
|
||||
struct gen_p *irs;
|
||||
|
||||
if (!(acc = memget(sizeof *acc))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(acc, 0x5e, sizeof *acc);
|
||||
if (!(irs = memget(sizeof *irs))) {
|
||||
errno = ENOMEM;
|
||||
memput(acc, sizeof *acc);
|
||||
return (NULL);
|
||||
}
|
||||
memset(irs, 0x5e, sizeof *irs);
|
||||
irs->options = strdup(options);
|
||||
irs->res = NULL;
|
||||
irs->free_res = NULL;
|
||||
memset(irs->accessors, 0, sizeof irs->accessors);
|
||||
memset(irs->map_rules, 0, sizeof irs->map_rules);
|
||||
init_map_rules(irs, conf_file);
|
||||
acc->private = irs;
|
||||
#ifdef WANT_IRS_GR
|
||||
acc->gr_map = irs_gen_gr;
|
||||
#else
|
||||
acc->gr_map = NULL;
|
||||
#endif
|
||||
#ifdef WANT_IRS_PW
|
||||
acc->pw_map = irs_gen_pw;
|
||||
#else
|
||||
acc->pw_map = NULL;
|
||||
#endif
|
||||
acc->sv_map = irs_gen_sv;
|
||||
acc->pr_map = irs_gen_pr;
|
||||
acc->ho_map = irs_gen_ho;
|
||||
acc->nw_map = irs_gen_nw;
|
||||
acc->ng_map = irs_gen_ng;
|
||||
acc->res_get = gen_res_get;
|
||||
acc->res_set = gen_res_set;
|
||||
acc->close = gen_close;
|
||||
return (acc);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static struct __res_state *
|
||||
gen_res_get(struct irs_acc *this) {
|
||||
struct gen_p *irs = (struct gen_p *)this->private;
|
||||
|
||||
if (irs->res == NULL) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
memset(res, 0, sizeof *res);
|
||||
gen_res_set(this, res, free);
|
||||
}
|
||||
|
||||
if (((irs->res->options & RES_INIT) == 0U) && res_ninit(irs->res) < 0)
|
||||
return (NULL);
|
||||
|
||||
return (irs->res);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_res_set(struct irs_acc *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct gen_p *irs = (struct gen_p *)this->private;
|
||||
#if 0
|
||||
struct irs_rule *rule;
|
||||
struct irs_ho *ho;
|
||||
struct irs_nw *nw;
|
||||
#endif
|
||||
|
||||
if (irs->res && irs->free_res) {
|
||||
res_nclose(irs->res);
|
||||
(*irs->free_res)(irs->res);
|
||||
}
|
||||
|
||||
irs->res = res;
|
||||
irs->free_res = free_res;
|
||||
|
||||
#if 0
|
||||
for (rule = irs->map_rules[irs_ho]; rule; rule = rule->next) {
|
||||
ho = rule->inst->ho;
|
||||
|
||||
(*ho->res_set)(ho, res, NULL);
|
||||
}
|
||||
for (rule = irs->map_rules[irs_nw]; rule; rule = rule->next) {
|
||||
nw = rule->inst->nw;
|
||||
|
||||
(*nw->res_set)(nw, res, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gen_close(struct irs_acc *this) {
|
||||
struct gen_p *irs = (struct gen_p *)this->private;
|
||||
int n;
|
||||
|
||||
/* Search rules. */
|
||||
for (n = 0; n < irs_nmap; n++)
|
||||
while (irs->map_rules[n] != NULL)
|
||||
irs->map_rules[n] = release_rule(irs->map_rules[n]);
|
||||
|
||||
/* Access methods. */
|
||||
for (n = 0; n < irs_nacc; n++) {
|
||||
/* Map objects. */
|
||||
if (irs->accessors[n].gr != NULL)
|
||||
(*irs->accessors[n].gr->close)(irs->accessors[n].gr);
|
||||
if (irs->accessors[n].pw != NULL)
|
||||
(*irs->accessors[n].pw->close)(irs->accessors[n].pw);
|
||||
if (irs->accessors[n].sv != NULL)
|
||||
(*irs->accessors[n].sv->close)(irs->accessors[n].sv);
|
||||
if (irs->accessors[n].pr != NULL)
|
||||
(*irs->accessors[n].pr->close)(irs->accessors[n].pr);
|
||||
if (irs->accessors[n].ho != NULL)
|
||||
(*irs->accessors[n].ho->close)(irs->accessors[n].ho);
|
||||
if (irs->accessors[n].nw != NULL)
|
||||
(*irs->accessors[n].nw->close)(irs->accessors[n].nw);
|
||||
if (irs->accessors[n].ng != NULL)
|
||||
(*irs->accessors[n].ng->close)(irs->accessors[n].ng);
|
||||
/* Enclosing accessor. */
|
||||
if (irs->accessors[n].acc != NULL)
|
||||
(*irs->accessors[n].acc->close)(irs->accessors[n].acc);
|
||||
}
|
||||
|
||||
/* The options string was strdup'd. */
|
||||
free((void*)irs->options);
|
||||
|
||||
if (irs->res && irs->free_res)
|
||||
(*irs->free_res)(irs->res);
|
||||
|
||||
/* The private data container. */
|
||||
memput(irs, sizeof *irs);
|
||||
|
||||
/* The object. */
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
static int
|
||||
find_name(const char *name, const struct nameval names[]) {
|
||||
int n;
|
||||
|
||||
for (n = 0; names[n].name != NULL; n++)
|
||||
if (strcmp(name, names[n].name) == 0)
|
||||
return (names[n].val);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static struct irs_rule *
|
||||
release_rule(struct irs_rule *rule) {
|
||||
struct irs_rule *next = rule->next;
|
||||
|
||||
memput(rule, sizeof *rule);
|
||||
return (next);
|
||||
}
|
||||
|
||||
static int
|
||||
add_rule(struct gen_p *irs,
|
||||
enum irs_map_id map, enum irs_acc_id acc,
|
||||
const char *options)
|
||||
{
|
||||
struct irs_rule **rules, *last, *tmp, *new;
|
||||
struct irs_inst *inst;
|
||||
const char *cp;
|
||||
int n;
|
||||
|
||||
#ifndef WANT_IRS_GR
|
||||
if (map == irs_gr)
|
||||
return (-1);
|
||||
#endif
|
||||
#ifndef WANT_IRS_PW
|
||||
if (map == irs_pw)
|
||||
return (-1);
|
||||
#endif
|
||||
#ifndef WANT_IRS_NIS
|
||||
if (acc == irs_nis)
|
||||
return (-1);
|
||||
#endif
|
||||
new = memget(sizeof *new);
|
||||
if (new == NULL)
|
||||
return (-1);
|
||||
memset(new, 0x5e, sizeof *new);
|
||||
new->next = NULL;
|
||||
|
||||
new->inst = &irs->accessors[acc];
|
||||
|
||||
new->flags = 0;
|
||||
cp = options;
|
||||
while (cp && *cp) {
|
||||
char option[50], *next;
|
||||
|
||||
next = strchr(cp, ',');
|
||||
if (next)
|
||||
n = next++ - cp;
|
||||
else
|
||||
n = strlen(cp);
|
||||
if ((size_t)n > sizeof option - 1)
|
||||
n = sizeof option - 1;
|
||||
strncpy(option, cp, n);
|
||||
option[n] = '\0';
|
||||
|
||||
n = find_name(option, option_names);
|
||||
if (n >= 0)
|
||||
new->flags |= n;
|
||||
|
||||
cp = next;
|
||||
}
|
||||
|
||||
rules = &irs->map_rules[map];
|
||||
for (last = NULL, tmp = *rules;
|
||||
tmp != NULL;
|
||||
last = tmp, tmp = tmp->next)
|
||||
(void)NULL;
|
||||
if (last == NULL)
|
||||
*rules = new;
|
||||
else
|
||||
last->next = new;
|
||||
|
||||
/* Try to instantiate map accessors for this if necessary & approp. */
|
||||
inst = &irs->accessors[acc];
|
||||
if (inst->acc == NULL && accs[acc] != NULL)
|
||||
inst->acc = (*accs[acc])(irs->options);
|
||||
if (inst->acc != NULL) {
|
||||
if (inst->gr == NULL && inst->acc->gr_map != NULL)
|
||||
inst->gr = (*inst->acc->gr_map)(inst->acc);
|
||||
if (inst->pw == NULL && inst->acc->pw_map != NULL)
|
||||
inst->pw = (*inst->acc->pw_map)(inst->acc);
|
||||
if (inst->sv == NULL && inst->acc->sv_map != NULL)
|
||||
inst->sv = (*inst->acc->sv_map)(inst->acc);
|
||||
if (inst->pr == NULL && inst->acc->pr_map != NULL)
|
||||
inst->pr = (*inst->acc->pr_map)(inst->acc);
|
||||
if (inst->ho == NULL && inst->acc->ho_map != NULL)
|
||||
inst->ho = (*inst->acc->ho_map)(inst->acc);
|
||||
if (inst->nw == NULL && inst->acc->nw_map != NULL)
|
||||
inst->nw = (*inst->acc->nw_map)(inst->acc);
|
||||
if (inst->ng == NULL && inst->acc->ng_map != NULL)
|
||||
inst->ng = (*inst->acc->ng_map)(inst->acc);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
default_map_rules(struct gen_p *irs) {
|
||||
/* Install time honoured and proved BSD style rules as default. */
|
||||
add_rule(irs, irs_gr, irs_lcl, "");
|
||||
add_rule(irs, irs_pw, irs_lcl, "");
|
||||
add_rule(irs, irs_sv, irs_lcl, "");
|
||||
add_rule(irs, irs_pr, irs_lcl, "");
|
||||
add_rule(irs, irs_ho, irs_dns, "continue");
|
||||
add_rule(irs, irs_ho, irs_lcl, "");
|
||||
add_rule(irs, irs_nw, irs_dns, "continue");
|
||||
add_rule(irs, irs_nw, irs_lcl, "");
|
||||
add_rule(irs, irs_ng, irs_lcl, "");
|
||||
}
|
||||
|
||||
static void
|
||||
init_map_rules(struct gen_p *irs, const char *conf_file) {
|
||||
char line[1024], pattern[40], mapname[20], accname[20], options[100];
|
||||
FILE *conf;
|
||||
|
||||
if (conf_file == NULL)
|
||||
conf_file = _PATH_IRS_CONF ;
|
||||
|
||||
/* A conf file of "" means compiled in defaults. Irpd wants this */
|
||||
if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) {
|
||||
default_map_rules(irs);
|
||||
return;
|
||||
}
|
||||
(void) sprintf(pattern, "%%%lus %%%lus %%%lus\n",
|
||||
(unsigned long)sizeof mapname,
|
||||
(unsigned long)sizeof accname,
|
||||
(unsigned long)sizeof options);
|
||||
while (fgets(line, sizeof line, conf)) {
|
||||
enum irs_map_id map;
|
||||
enum irs_acc_id acc;
|
||||
char *tmp;
|
||||
int n;
|
||||
|
||||
for (tmp = line;
|
||||
isascii((unsigned char)*tmp) &&
|
||||
isspace((unsigned char)*tmp);
|
||||
tmp++)
|
||||
(void)NULL;
|
||||
if (*tmp == '#' || *tmp == '\n' || *tmp == '\0')
|
||||
continue;
|
||||
n = sscanf(tmp, pattern, mapname, accname, options);
|
||||
if (n < 2)
|
||||
continue;
|
||||
if (n < 3)
|
||||
options[0] = '\0';
|
||||
|
||||
n = find_name(mapname, map_names);
|
||||
INSIST(n < irs_nmap);
|
||||
if (n < 0)
|
||||
continue;
|
||||
map = (enum irs_map_id) n;
|
||||
|
||||
n = find_name(accname, acc_names);
|
||||
INSIST(n < irs_nacc);
|
||||
if (n < 0)
|
||||
continue;
|
||||
acc = (enum irs_acc_id) n;
|
||||
|
||||
add_rule(irs, map, acc, options);
|
||||
}
|
||||
fclose(conf);
|
||||
}
|
||||
@@ -1,391 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "gen_p.h"
|
||||
|
||||
/* Definitions */
|
||||
|
||||
struct pvt {
|
||||
struct irs_rule * rules;
|
||||
struct irs_rule * rule;
|
||||
struct irs_ho * ho;
|
||||
struct __res_state * res;
|
||||
void (*free_res)(void *);
|
||||
};
|
||||
|
||||
/* Forwards */
|
||||
|
||||
static void ho_close(struct irs_ho *this);
|
||||
static struct hostent * ho_byname(struct irs_ho *this, const char *name);
|
||||
static struct hostent * ho_byname2(struct irs_ho *this, const char *name,
|
||||
int af);
|
||||
static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
|
||||
int len, int af);
|
||||
static struct hostent * ho_next(struct irs_ho *this);
|
||||
static void ho_rewind(struct irs_ho *this);
|
||||
static void ho_minimize(struct irs_ho *this);
|
||||
static struct __res_state * ho_res_get(struct irs_ho *this);
|
||||
static void ho_res_set(struct irs_ho *this,
|
||||
struct __res_state *res,
|
||||
void (*free_res)(void *));
|
||||
static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name,
|
||||
const struct addrinfo *pai);
|
||||
|
||||
static int init(struct irs_ho *this);
|
||||
|
||||
/* Exports */
|
||||
|
||||
struct irs_ho *
|
||||
irs_gen_ho(struct irs_acc *this) {
|
||||
struct gen_p *accpvt = (struct gen_p *)this->private;
|
||||
struct irs_ho *ho;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
if (!(ho = memget(sizeof *ho))) {
|
||||
memput(pvt, sizeof *pvt);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(ho, 0x5e, sizeof *ho);
|
||||
pvt->rules = accpvt->map_rules[irs_ho];
|
||||
pvt->rule = pvt->rules;
|
||||
ho->private = pvt;
|
||||
ho->close = ho_close;
|
||||
ho->byname = ho_byname;
|
||||
ho->byname2 = ho_byname2;
|
||||
ho->byaddr = ho_byaddr;
|
||||
ho->next = ho_next;
|
||||
ho->rewind = ho_rewind;
|
||||
ho->minimize = ho_minimize;
|
||||
ho->res_get = ho_res_get;
|
||||
ho->res_set = ho_res_set;
|
||||
ho->addrinfo = ho_addrinfo;
|
||||
return (ho);
|
||||
}
|
||||
|
||||
/* Methods. */
|
||||
|
||||
static void
|
||||
ho_close(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
ho_minimize(this);
|
||||
if (pvt->res && pvt->free_res)
|
||||
(*pvt->free_res)(pvt->res);
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct hostent *
|
||||
ho_byname(struct irs_ho *this, const char *name) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct hostent *rval;
|
||||
struct irs_ho *ho;
|
||||
int therrno = NETDB_INTERNAL;
|
||||
int softerror = 0;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
ho = rule->inst->ho;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
errno = 0;
|
||||
rval = (*ho->byname)(ho, name);
|
||||
if (rval != NULL)
|
||||
return (rval);
|
||||
if (softerror == 0 &&
|
||||
pvt->res->res_h_errno != HOST_NOT_FOUND &&
|
||||
pvt->res->res_h_errno != NETDB_INTERNAL) {
|
||||
softerror = 1;
|
||||
therrno = pvt->res->res_h_errno;
|
||||
}
|
||||
if (rule->flags & IRS_CONTINUE)
|
||||
continue;
|
||||
/*
|
||||
* The value TRY_AGAIN can mean that the service
|
||||
* is not available, or just that this particular name
|
||||
* cannot be resolved now. We use the errno ECONNREFUSED
|
||||
* to distinguish. If a lookup sets that errno when
|
||||
* H_ERRNO is TRY_AGAIN, we continue to try other lookup
|
||||
* functions, otherwise we return the TRY_AGAIN error.
|
||||
*/
|
||||
if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED)
|
||||
break;
|
||||
}
|
||||
if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND)
|
||||
RES_SET_H_ERRNO(pvt->res, therrno);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct hostent *
|
||||
ho_byname2(struct irs_ho *this, const char *name, int af) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct hostent *rval;
|
||||
struct irs_ho *ho;
|
||||
int therrno = NETDB_INTERNAL;
|
||||
int softerror = 0;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
ho = rule->inst->ho;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
errno = 0;
|
||||
rval = (*ho->byname2)(ho, name, af);
|
||||
if (rval != NULL)
|
||||
return (rval);
|
||||
if (softerror == 0 &&
|
||||
pvt->res->res_h_errno != HOST_NOT_FOUND &&
|
||||
pvt->res->res_h_errno != NETDB_INTERNAL) {
|
||||
softerror = 1;
|
||||
therrno = pvt->res->res_h_errno;
|
||||
}
|
||||
if (rule->flags & IRS_CONTINUE)
|
||||
continue;
|
||||
/*
|
||||
* See the comments in ho_byname() explaining
|
||||
* the interpretation of TRY_AGAIN and ECONNREFUSED.
|
||||
*/
|
||||
if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED)
|
||||
break;
|
||||
}
|
||||
if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND)
|
||||
RES_SET_H_ERRNO(pvt->res, therrno);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct hostent *
|
||||
ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct hostent *rval;
|
||||
struct irs_ho *ho;
|
||||
int therrno = NETDB_INTERNAL;
|
||||
int softerror = 0;
|
||||
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
ho = rule->inst->ho;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
errno = 0;
|
||||
rval = (*ho->byaddr)(ho, addr, len, af);
|
||||
if (rval != NULL)
|
||||
return (rval);
|
||||
if (softerror == 0 &&
|
||||
pvt->res->res_h_errno != HOST_NOT_FOUND &&
|
||||
pvt->res->res_h_errno != NETDB_INTERNAL) {
|
||||
softerror = 1;
|
||||
therrno = pvt->res->res_h_errno;
|
||||
}
|
||||
|
||||
if (rule->flags & IRS_CONTINUE)
|
||||
continue;
|
||||
/*
|
||||
* See the comments in ho_byname() explaining
|
||||
* the interpretation of TRY_AGAIN and ECONNREFUSED.
|
||||
*/
|
||||
if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED)
|
||||
break;
|
||||
}
|
||||
if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND)
|
||||
RES_SET_H_ERRNO(pvt->res, therrno);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct hostent *
|
||||
ho_next(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct hostent *rval;
|
||||
struct irs_ho *ho;
|
||||
|
||||
while (pvt->rule) {
|
||||
ho = pvt->rule->inst->ho;
|
||||
rval = (*ho->next)(ho);
|
||||
if (rval)
|
||||
return (rval);
|
||||
if (!(pvt->rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
pvt->rule = pvt->rule->next;
|
||||
if (pvt->rule) {
|
||||
ho = pvt->rule->inst->ho;
|
||||
(*ho->rewind)(ho);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
ho_rewind(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_ho *ho;
|
||||
|
||||
pvt->rule = pvt->rules;
|
||||
if (pvt->rule) {
|
||||
ho = pvt->rule->inst->ho;
|
||||
(*ho->rewind)(ho);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ho_minimize(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
if (pvt->res)
|
||||
res_nclose(pvt->res);
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_ho *ho = rule->inst->ho;
|
||||
|
||||
(*ho->minimize)(ho);
|
||||
}
|
||||
}
|
||||
|
||||
static struct __res_state *
|
||||
ho_res_get(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (!res) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof *res);
|
||||
ho_res_set(this, res, free);
|
||||
}
|
||||
|
||||
return (pvt->res);
|
||||
}
|
||||
|
||||
static void
|
||||
ho_res_set(struct irs_ho *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
if (pvt->res && pvt->free_res) {
|
||||
res_nclose(pvt->res);
|
||||
(*pvt->free_res)(pvt->res);
|
||||
}
|
||||
|
||||
pvt->res = res;
|
||||
pvt->free_res = free_res;
|
||||
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_ho *ho = rule->inst->ho;
|
||||
|
||||
(*ho->res_set)(ho, pvt->res, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static struct addrinfo *
|
||||
ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai)
|
||||
{
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct addrinfo *rval = NULL;
|
||||
struct irs_ho *ho;
|
||||
int therrno = NETDB_INTERNAL;
|
||||
int softerror = 0;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
ho = rule->inst->ho;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
errno = 0;
|
||||
if (ho->addrinfo == NULL) /* for safety */
|
||||
continue;
|
||||
rval = (*ho->addrinfo)(ho, name, pai);
|
||||
if (rval != NULL)
|
||||
return (rval);
|
||||
if (softerror == 0 &&
|
||||
pvt->res->res_h_errno != HOST_NOT_FOUND &&
|
||||
pvt->res->res_h_errno != NETDB_INTERNAL) {
|
||||
softerror = 1;
|
||||
therrno = pvt->res->res_h_errno;
|
||||
}
|
||||
if (rule->flags & IRS_CONTINUE)
|
||||
continue;
|
||||
/*
|
||||
* See the comments in ho_byname() explaining
|
||||
* the interpretation of TRY_AGAIN and ECONNREFUSED.
|
||||
*/
|
||||
if (pvt->res->res_h_errno != TRY_AGAIN ||
|
||||
errno != ECONNREFUSED)
|
||||
break;
|
||||
}
|
||||
if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND)
|
||||
RES_SET_H_ERRNO(pvt->res, therrno);
|
||||
if (rval)
|
||||
freeaddrinfo(rval);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
init(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res && !ho_res_get(this))
|
||||
return (-1);
|
||||
|
||||
if (((pvt->res->options & RES_INIT) == 0U) &&
|
||||
(res_ninit(pvt->res) == -1))
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "gen_p.h"
|
||||
|
||||
/* Types */
|
||||
|
||||
struct pvt {
|
||||
struct irs_rule * rules;
|
||||
struct irs_rule * rule;
|
||||
char * curgroup;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void ng_close(struct irs_ng *);
|
||||
static int ng_next(struct irs_ng *, const char **,
|
||||
const char **, const char **);
|
||||
static int ng_test(struct irs_ng *, const char *,
|
||||
const char *, const char *,
|
||||
const char *);
|
||||
static void ng_rewind(struct irs_ng *, const char *);
|
||||
static void ng_minimize(struct irs_ng *);
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_ng *
|
||||
irs_gen_ng(struct irs_acc *this) {
|
||||
struct gen_p *accpvt = (struct gen_p *)this->private;
|
||||
struct irs_ng *ng;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(ng = memget(sizeof *ng))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(ng, 0x5e, sizeof *ng);
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
memput(ng, sizeof *ng);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pvt->rules = accpvt->map_rules[irs_ng];
|
||||
pvt->rule = pvt->rules;
|
||||
ng->private = pvt;
|
||||
ng->close = ng_close;
|
||||
ng->next = ng_next;
|
||||
ng->test = ng_test;
|
||||
ng->rewind = ng_rewind;
|
||||
ng->minimize = ng_minimize;
|
||||
return (ng);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
ng_close(struct irs_ng *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
ng_minimize(this);
|
||||
if (pvt->curgroup)
|
||||
free(pvt->curgroup);
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static int
|
||||
ng_next(struct irs_ng *this, const char **host, const char **user,
|
||||
const char **domain)
|
||||
{
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_ng *ng;
|
||||
|
||||
while (pvt->rule) {
|
||||
ng = pvt->rule->inst->ng;
|
||||
if ((*ng->next)(ng, host, user, domain) == 1)
|
||||
return (1);
|
||||
if (!(pvt->rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
pvt->rule = pvt->rule->next;
|
||||
if (pvt->rule) {
|
||||
ng = pvt->rule->inst->ng;
|
||||
(*ng->rewind)(ng, pvt->curgroup);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ng_test(struct irs_ng *this, const char *name,
|
||||
const char *user, const char *host, const char *domain)
|
||||
{
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct irs_ng *ng;
|
||||
int rval;
|
||||
|
||||
rval = 0;
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
ng = rule->inst->ng;
|
||||
rval = (*ng->test)(ng, name, user, host, domain);
|
||||
if (rval || !(rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
}
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static void
|
||||
ng_rewind(struct irs_ng *this, const char *group) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_ng *ng;
|
||||
|
||||
pvt->rule = pvt->rules;
|
||||
if (pvt->rule) {
|
||||
if (pvt->curgroup)
|
||||
free(pvt->curgroup);
|
||||
pvt->curgroup = strdup(group);
|
||||
ng = pvt->rule->inst->ng;
|
||||
(*ng->rewind)(ng, pvt->curgroup);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ng_minimize(struct irs_ng *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_ng *ng = rule->inst->ng;
|
||||
|
||||
(*ng->minimize)(ng);
|
||||
}
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <resolv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "gen_p.h"
|
||||
|
||||
/* Types */
|
||||
|
||||
struct pvt {
|
||||
struct irs_rule * rules;
|
||||
struct irs_rule * rule;
|
||||
struct __res_state * res;
|
||||
void (*free_res)(void *);
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void nw_close(struct irs_nw*);
|
||||
static struct nwent * nw_next(struct irs_nw *);
|
||||
static struct nwent * nw_byname(struct irs_nw *, const char *, int);
|
||||
static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int);
|
||||
static void nw_rewind(struct irs_nw *);
|
||||
static void nw_minimize(struct irs_nw *);
|
||||
static struct __res_state * nw_res_get(struct irs_nw *this);
|
||||
static void nw_res_set(struct irs_nw *this,
|
||||
struct __res_state *res,
|
||||
void (*free_res)(void *));
|
||||
|
||||
static int init(struct irs_nw *this);
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_nw *
|
||||
irs_gen_nw(struct irs_acc *this) {
|
||||
struct gen_p *accpvt = (struct gen_p *)this->private;
|
||||
struct irs_nw *nw;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
if (!(nw = memget(sizeof *nw))) {
|
||||
memput(pvt, sizeof *pvt);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(nw, 0x5e, sizeof *nw);
|
||||
pvt->rules = accpvt->map_rules[irs_nw];
|
||||
pvt->rule = pvt->rules;
|
||||
nw->private = pvt;
|
||||
nw->close = nw_close;
|
||||
nw->next = nw_next;
|
||||
nw->byname = nw_byname;
|
||||
nw->byaddr = nw_byaddr;
|
||||
nw->rewind = nw_rewind;
|
||||
nw->minimize = nw_minimize;
|
||||
nw->res_get = nw_res_get;
|
||||
nw->res_set = nw_res_set;
|
||||
return (nw);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
nw_close(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
nw_minimize(this);
|
||||
|
||||
if (pvt->res && pvt->free_res)
|
||||
(*pvt->free_res)(pvt->res);
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_next(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct nwent *rval;
|
||||
struct irs_nw *nw;
|
||||
|
||||
if (init(this) == -1)
|
||||
return(NULL);
|
||||
|
||||
while (pvt->rule) {
|
||||
nw = pvt->rule->inst->nw;
|
||||
rval = (*nw->next)(nw);
|
||||
if (rval)
|
||||
return (rval);
|
||||
if (!(pvt->rules->flags & IRS_CONTINUE))
|
||||
break;
|
||||
pvt->rule = pvt->rule->next;
|
||||
if (pvt->rule) {
|
||||
nw = pvt->rule->inst->nw;
|
||||
(*nw->rewind)(nw);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_byname(struct irs_nw *this, const char *name, int type) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct nwent *rval;
|
||||
struct irs_nw *nw;
|
||||
|
||||
if (init(this) == -1)
|
||||
return(NULL);
|
||||
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
nw = rule->inst->nw;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
rval = (*nw->byname)(nw, name, type);
|
||||
if (rval != NULL)
|
||||
return (rval);
|
||||
if (pvt->res->res_h_errno != TRY_AGAIN &&
|
||||
!(rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_byaddr(struct irs_nw *this, void *net, int length, int type) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct nwent *rval;
|
||||
struct irs_nw *nw;
|
||||
|
||||
if (init(this) == -1)
|
||||
return(NULL);
|
||||
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
nw = rule->inst->nw;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
rval = (*nw->byaddr)(nw, net, length, type);
|
||||
if (rval != NULL)
|
||||
return (rval);
|
||||
if (pvt->res->res_h_errno != TRY_AGAIN &&
|
||||
!(rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
nw_rewind(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_nw *nw;
|
||||
|
||||
pvt->rule = pvt->rules;
|
||||
if (pvt->rule) {
|
||||
nw = pvt->rule->inst->nw;
|
||||
(*nw->rewind)(nw);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nw_minimize(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
if (pvt->res)
|
||||
res_nclose(pvt->res);
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_nw *nw = rule->inst->nw;
|
||||
|
||||
(*nw->minimize)(nw);
|
||||
}
|
||||
}
|
||||
|
||||
static struct __res_state *
|
||||
nw_res_get(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (!res) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof *res);
|
||||
nw_res_set(this, res, free);
|
||||
}
|
||||
|
||||
return (pvt->res);
|
||||
}
|
||||
|
||||
static void
|
||||
nw_res_set(struct irs_nw *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
if (pvt->res && pvt->free_res) {
|
||||
res_nclose(pvt->res);
|
||||
(*pvt->free_res)(pvt->res);
|
||||
}
|
||||
|
||||
pvt->res = res;
|
||||
pvt->free_res = free_res;
|
||||
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_nw *nw = rule->inst->nw;
|
||||
|
||||
(*nw->res_set)(nw, pvt->res, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
init(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res && !nw_res_get(this))
|
||||
return (-1);
|
||||
if (((pvt->res->options & RES_INIT) == 0U) &&
|
||||
res_ninit(pvt->res) == -1)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* Notes:
|
||||
* We hope to create a complete set of thread-safe entry points someday,
|
||||
* which will mean a set of getXbyY() functions that take as an argument
|
||||
* a pointer to the map class, which will have a pointer to the private
|
||||
* data, which will be used preferentially to the static variables that
|
||||
* are necessary to support the "classic" interface. This "classic"
|
||||
* interface will then be reimplemented as stubs on top of the thread
|
||||
* safe modules, and will keep the map class pointers as their only
|
||||
* static data. HOWEVER, we are not there yet. So while we will call
|
||||
* the just-barely-converted map class methods with map class pointers,
|
||||
* right now they probably all still use statics. We're not fooling
|
||||
* anybody, and we're not trying to (yet).
|
||||
*/
|
||||
|
||||
#ifndef _GEN_P_H_INCLUDED
|
||||
#define _GEN_P_H_INCLUDED
|
||||
|
||||
/*
|
||||
* These are the access methods.
|
||||
*/
|
||||
enum irs_acc_id {
|
||||
irs_lcl, /* Local. */
|
||||
irs_dns, /* DNS or Hesiod. */
|
||||
irs_nis, /* Sun NIS ("YP"). */
|
||||
irs_irp, /* IR protocol. */
|
||||
irs_nacc
|
||||
};
|
||||
|
||||
/*
|
||||
* These are the map types.
|
||||
*/
|
||||
enum irs_map_id {
|
||||
irs_gr, /* "group" */
|
||||
irs_pw, /* "passwd" */
|
||||
irs_sv, /* "services" */
|
||||
irs_pr, /* "protocols" */
|
||||
irs_ho, /* "hosts" */
|
||||
irs_nw, /* "networks" */
|
||||
irs_ng, /* "netgroup" */
|
||||
irs_nmap
|
||||
};
|
||||
|
||||
/*
|
||||
* This is an accessor instance.
|
||||
*/
|
||||
struct irs_inst {
|
||||
struct irs_acc *acc;
|
||||
struct irs_gr * gr;
|
||||
struct irs_pw * pw;
|
||||
struct irs_sv * sv;
|
||||
struct irs_pr * pr;
|
||||
struct irs_ho * ho;
|
||||
struct irs_nw * nw;
|
||||
struct irs_ng * ng;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a search rule for some map type.
|
||||
*/
|
||||
struct irs_rule {
|
||||
struct irs_rule * next;
|
||||
struct irs_inst * inst;
|
||||
int flags;
|
||||
};
|
||||
#define IRS_MERGE 0x0001 /* Don't stop if acc. has data? */
|
||||
#define IRS_CONTINUE 0x0002 /* Don't stop if acc. has no data? */
|
||||
|
||||
/*
|
||||
* This is the private data for a search access class.
|
||||
*/
|
||||
struct gen_p {
|
||||
char * options;
|
||||
struct irs_rule * map_rules[(int)irs_nmap];
|
||||
struct irs_inst accessors[(int)irs_nacc];
|
||||
struct __res_state * res;
|
||||
void (*free_res) __P((void *));
|
||||
};
|
||||
|
||||
/*
|
||||
* Externs.
|
||||
*/
|
||||
|
||||
extern struct irs_acc * irs_gen_acc __P((const char *, const char *conf_file));
|
||||
extern struct irs_gr * irs_gen_gr __P((struct irs_acc *));
|
||||
extern struct irs_pw * irs_gen_pw __P((struct irs_acc *));
|
||||
extern struct irs_sv * irs_gen_sv __P((struct irs_acc *));
|
||||
extern struct irs_pr * irs_gen_pr __P((struct irs_acc *));
|
||||
extern struct irs_ho * irs_gen_ho __P((struct irs_acc *));
|
||||
extern struct irs_nw * irs_gen_nw __P((struct irs_acc *));
|
||||
extern struct irs_ng * irs_gen_ng __P((struct irs_acc *));
|
||||
|
||||
#endif /*_IRS_P_H_INCLUDED*/
|
||||
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <resolv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "gen_p.h"
|
||||
|
||||
/* Types */
|
||||
|
||||
struct pvt {
|
||||
struct irs_rule * rules;
|
||||
struct irs_rule * rule;
|
||||
struct __res_state * res;
|
||||
void (*free_res)(void *);
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void pr_close(struct irs_pr*);
|
||||
static struct protoent * pr_next(struct irs_pr *);
|
||||
static struct protoent * pr_byname(struct irs_pr *, const char *);
|
||||
static struct protoent * pr_bynumber(struct irs_pr *, int);
|
||||
static void pr_rewind(struct irs_pr *);
|
||||
static void pr_minimize(struct irs_pr *);
|
||||
static struct __res_state * pr_res_get(struct irs_pr *);
|
||||
static void pr_res_set(struct irs_pr *,
|
||||
struct __res_state *,
|
||||
void (*)(void *));
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_pr *
|
||||
irs_gen_pr(struct irs_acc *this) {
|
||||
struct gen_p *accpvt = (struct gen_p *)this->private;
|
||||
struct irs_pr *pr;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(pr = memget(sizeof *pr))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pr, 0x5e, sizeof *pr);
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
memput(pr, sizeof *pr);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pvt->rules = accpvt->map_rules[irs_pr];
|
||||
pvt->rule = pvt->rules;
|
||||
pr->private = pvt;
|
||||
pr->close = pr_close;
|
||||
pr->next = pr_next;
|
||||
pr->byname = pr_byname;
|
||||
pr->bynumber = pr_bynumber;
|
||||
pr->rewind = pr_rewind;
|
||||
pr->minimize = pr_minimize;
|
||||
pr->res_get = pr_res_get;
|
||||
pr->res_set = pr_res_set;
|
||||
return (pr);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
pr_close(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_next(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct protoent *rval;
|
||||
struct irs_pr *pr;
|
||||
|
||||
while (pvt->rule) {
|
||||
pr = pvt->rule->inst->pr;
|
||||
rval = (*pr->next)(pr);
|
||||
if (rval)
|
||||
return (rval);
|
||||
if (!(pvt->rules->flags & IRS_CONTINUE))
|
||||
break;
|
||||
pvt->rule = pvt->rule->next;
|
||||
if (pvt->rule) {
|
||||
pr = pvt->rule->inst->pr;
|
||||
(*pr->rewind)(pr);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_byname(struct irs_pr *this, const char *name) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct protoent *rval;
|
||||
struct irs_pr *pr;
|
||||
|
||||
rval = NULL;
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
pr = rule->inst->pr;
|
||||
rval = (*pr->byname)(pr, name);
|
||||
if (rval || !(rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
}
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_bynumber(struct irs_pr *this, int proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct protoent *rval;
|
||||
struct irs_pr *pr;
|
||||
|
||||
rval = NULL;
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
pr = rule->inst->pr;
|
||||
rval = (*pr->bynumber)(pr, proto);
|
||||
if (rval || !(rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
}
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_rewind(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_pr *pr;
|
||||
|
||||
pvt->rule = pvt->rules;
|
||||
if (pvt->rule) {
|
||||
pr = pvt->rule->inst->pr;
|
||||
(*pr->rewind)(pr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pr_minimize(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_pr *pr = rule->inst->pr;
|
||||
|
||||
(*pr->minimize)(pr);
|
||||
}
|
||||
}
|
||||
|
||||
static struct __res_state *
|
||||
pr_res_get(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (!res) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof *res);
|
||||
pr_res_set(this, res, free);
|
||||
}
|
||||
|
||||
return (pvt->res);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_res_set(struct irs_pr *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
if (pvt->res && pvt->free_res) {
|
||||
res_nclose(pvt->res);
|
||||
(*pvt->free_res)(pvt->res);
|
||||
}
|
||||
|
||||
pvt->res = res;
|
||||
pvt->free_res = free_res;
|
||||
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_pr *pr = rule->inst->pr;
|
||||
|
||||
if (pr->res_set)
|
||||
(*pr->res_set)(pr, pvt->res, NULL);
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "gen_p.h"
|
||||
|
||||
/* Types */
|
||||
|
||||
struct pvt {
|
||||
struct irs_rule * rules;
|
||||
struct irs_rule * rule;
|
||||
struct __res_state * res;
|
||||
void (*free_res)(void *);
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void sv_close(struct irs_sv*);
|
||||
static struct servent * sv_next(struct irs_sv *);
|
||||
static struct servent * sv_byname(struct irs_sv *, const char *,
|
||||
const char *);
|
||||
static struct servent * sv_byport(struct irs_sv *, int, const char *);
|
||||
static void sv_rewind(struct irs_sv *);
|
||||
static void sv_minimize(struct irs_sv *);
|
||||
static struct __res_state * sv_res_get(struct irs_sv *);
|
||||
static void sv_res_set(struct irs_sv *,
|
||||
struct __res_state *,
|
||||
void (*)(void *));
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_sv *
|
||||
irs_gen_sv(struct irs_acc *this) {
|
||||
struct gen_p *accpvt = (struct gen_p *)this->private;
|
||||
struct irs_sv *sv;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(sv = memget(sizeof *sv))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(sv, 0x5e, sizeof *sv);
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
memput(sv, sizeof *sv);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pvt->rules = accpvt->map_rules[irs_sv];
|
||||
pvt->rule = pvt->rules;
|
||||
sv->private = pvt;
|
||||
sv->close = sv_close;
|
||||
sv->next = sv_next;
|
||||
sv->byname = sv_byname;
|
||||
sv->byport = sv_byport;
|
||||
sv->rewind = sv_rewind;
|
||||
sv->minimize = sv_minimize;
|
||||
sv->res_get = sv_res_get;
|
||||
sv->res_set = sv_res_set;
|
||||
return (sv);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
sv_close(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_next(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct servent *rval;
|
||||
struct irs_sv *sv;
|
||||
|
||||
while (pvt->rule) {
|
||||
sv = pvt->rule->inst->sv;
|
||||
rval = (*sv->next)(sv);
|
||||
if (rval)
|
||||
return (rval);
|
||||
if (!(pvt->rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
pvt->rule = pvt->rule->next;
|
||||
if (pvt->rule) {
|
||||
sv = pvt->rule->inst->sv;
|
||||
(*sv->rewind)(sv);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_byname(struct irs_sv *this, const char *name, const char *proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct servent *rval;
|
||||
struct irs_sv *sv;
|
||||
|
||||
rval = NULL;
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
sv = rule->inst->sv;
|
||||
rval = (*sv->byname)(sv, name, proto);
|
||||
if (rval || !(rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
}
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_byport(struct irs_sv *this, int port, const char *proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
struct servent *rval;
|
||||
struct irs_sv *sv;
|
||||
|
||||
rval = NULL;
|
||||
for (rule = pvt->rules; rule; rule = rule->next) {
|
||||
sv = rule->inst->sv;
|
||||
rval = (*sv->byport)(sv, port, proto);
|
||||
if (rval || !(rule->flags & IRS_CONTINUE))
|
||||
break;
|
||||
}
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static void
|
||||
sv_rewind(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_sv *sv;
|
||||
|
||||
pvt->rule = pvt->rules;
|
||||
if (pvt->rule) {
|
||||
sv = pvt->rule->inst->sv;
|
||||
(*sv->rewind)(sv);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sv_minimize(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_sv *sv = rule->inst->sv;
|
||||
|
||||
(*sv->minimize)(sv);
|
||||
}
|
||||
}
|
||||
|
||||
static struct __res_state *
|
||||
sv_res_get(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (!res) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof *res);
|
||||
sv_res_set(this, res, free);
|
||||
}
|
||||
|
||||
return (pvt->res);
|
||||
}
|
||||
|
||||
static void
|
||||
sv_res_set(struct irs_sv *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct irs_rule *rule;
|
||||
|
||||
if (pvt->res && pvt->free_res) {
|
||||
res_nclose(pvt->res);
|
||||
(*pvt->free_res)(pvt->res);
|
||||
}
|
||||
|
||||
pvt->res = res;
|
||||
pvt->free_res = free_res;
|
||||
|
||||
for (rule = pvt->rules; rule != NULL; rule = rule->next) {
|
||||
struct irs_sv *sv = rule->inst->sv;
|
||||
|
||||
if (sv->res_set)
|
||||
(*sv->res_set)(sv, pvt->res, NULL);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,262 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <port_before.h>
|
||||
#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
|
||||
static int gethostent_r_not_required = 0;
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/param.h>
|
||||
#include <port_after.h>
|
||||
|
||||
#ifdef HOST_R_RETURN
|
||||
|
||||
static HOST_R_RETURN
|
||||
copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS);
|
||||
|
||||
HOST_R_RETURN
|
||||
gethostbyname_r(const char *name, struct hostent *hptr, HOST_R_ARGS) {
|
||||
struct hostent *he = gethostbyname(name);
|
||||
#ifdef HOST_R_SETANSWER
|
||||
int n = 0;
|
||||
#endif
|
||||
|
||||
HOST_R_ERRNO;
|
||||
|
||||
#ifdef HOST_R_SETANSWER
|
||||
if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = hptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (he == NULL)
|
||||
return (HOST_R_BAD);
|
||||
|
||||
return (copy_hostent(he, hptr, HOST_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
HOST_R_RETURN
|
||||
gethostbyaddr_r(const char *addr, int len, int type,
|
||||
struct hostent *hptr, HOST_R_ARGS) {
|
||||
struct hostent *he = gethostbyaddr(addr, len, type);
|
||||
#ifdef HOST_R_SETANSWER
|
||||
int n = 0;
|
||||
#endif
|
||||
|
||||
HOST_R_ERRNO;
|
||||
|
||||
#ifdef HOST_R_SETANSWER
|
||||
if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = hptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (he == NULL)
|
||||
return (HOST_R_BAD);
|
||||
|
||||
return (copy_hostent(he, hptr, HOST_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* These assume a single context is in operation per thread.
|
||||
* If this is not the case we will need to call irs directly
|
||||
* rather than through the base functions.
|
||||
*/
|
||||
|
||||
HOST_R_RETURN
|
||||
gethostent_r(struct hostent *hptr, HOST_R_ARGS) {
|
||||
struct hostent *he = gethostent();
|
||||
#ifdef HOST_R_SETANSWER
|
||||
int n = 0;
|
||||
#endif
|
||||
|
||||
HOST_R_ERRNO;
|
||||
|
||||
#ifdef HOST_R_SETANSWER
|
||||
if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = hptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (he == NULL)
|
||||
return (HOST_R_BAD);
|
||||
|
||||
return (copy_hostent(he, hptr, HOST_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
HOST_R_SET_RETURN
|
||||
#ifdef HOST_R_ENT_ARGS
|
||||
sethostent_r(int stay_open, HOST_R_ENT_ARGS)
|
||||
#else
|
||||
sethostent_r(int stay_open)
|
||||
#endif
|
||||
{
|
||||
sethostent(stay_open);
|
||||
#ifdef HOST_R_SET_RESULT
|
||||
return (HOST_R_SET_RESULT);
|
||||
#endif
|
||||
}
|
||||
|
||||
HOST_R_END_RETURN
|
||||
#ifdef HOST_R_ENT_ARGS
|
||||
endhostent_r(HOST_R_ENT_ARGS)
|
||||
#else
|
||||
endhostent_r(void)
|
||||
#endif
|
||||
{
|
||||
endhostent();
|
||||
HOST_R_END_RESULT(HOST_R_OK);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
#ifndef HOSTENT_DATA
|
||||
static HOST_R_RETURN
|
||||
copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) {
|
||||
char *cp;
|
||||
char **ptr;
|
||||
int i, n;
|
||||
int nptr, len;
|
||||
|
||||
/* Find out the amount of space required to store the answer. */
|
||||
nptr = 2; /* NULL ptrs */
|
||||
len = (char *)ALIGN(buf) - buf;
|
||||
for (i = 0; he->h_addr_list[i]; i++, nptr++) {
|
||||
len += he->h_length;
|
||||
}
|
||||
for (i = 0; he->h_aliases[i]; i++, nptr++) {
|
||||
len += strlen(he->h_aliases[i]) + 1;
|
||||
}
|
||||
len += strlen(he->h_name) + 1;
|
||||
len += nptr * sizeof(char*);
|
||||
|
||||
if (len > buflen) {
|
||||
errno = ERANGE;
|
||||
return (HOST_R_BAD);
|
||||
}
|
||||
|
||||
/* copy address size and type */
|
||||
hptr->h_addrtype = he->h_addrtype;
|
||||
n = hptr->h_length = he->h_length;
|
||||
|
||||
ptr = (char **)ALIGN(buf);
|
||||
cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
|
||||
|
||||
/* copy address list */
|
||||
hptr->h_addr_list = ptr;
|
||||
for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
|
||||
memcpy(cp, he->h_addr_list[i], n);
|
||||
hptr->h_addr_list[i] = cp;
|
||||
cp += n;
|
||||
}
|
||||
hptr->h_addr_list[i] = NULL;
|
||||
ptr++;
|
||||
|
||||
/* copy official name */
|
||||
n = strlen(he->h_name) + 1;
|
||||
strcpy(cp, he->h_name);
|
||||
hptr->h_name = cp;
|
||||
cp += n;
|
||||
|
||||
/* copy aliases */
|
||||
hptr->h_aliases = ptr;
|
||||
for (i = 0 ; he->h_aliases[i]; i++) {
|
||||
n = strlen(he->h_aliases[i]) + 1;
|
||||
strcpy(cp, he->h_aliases[i]);
|
||||
hptr->h_aliases[i] = cp;
|
||||
cp += n;
|
||||
}
|
||||
hptr->h_aliases[i] = NULL;
|
||||
|
||||
return (HOST_R_OK);
|
||||
}
|
||||
#else /* !HOSTENT_DATA */
|
||||
static int
|
||||
copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) {
|
||||
char *cp, *eob;
|
||||
int i, n;
|
||||
|
||||
/* copy address size and type */
|
||||
hptr->h_addrtype = he->h_addrtype;
|
||||
n = hptr->h_length = he->h_length;
|
||||
|
||||
/* copy up to first 35 addresses */
|
||||
i = 0;
|
||||
cp = hdptr->hostbuf;
|
||||
eob = hdptr->hostbuf + sizeof(hdptr->hostbuf);
|
||||
hptr->h_addr_list = hdptr->h_addr_ptrs;
|
||||
while (he->h_addr_list[i] && i < (_MAXADDRS)) {
|
||||
if (n < (eob - cp)) {
|
||||
memcpy(cp, he->h_addr_list[i], n);
|
||||
hptr->h_addr_list[i] = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
hptr->h_addr_list[i] = NULL;
|
||||
|
||||
/* copy official name */
|
||||
if ((n = strlen(he->h_name) + 1) < (eob - cp)) {
|
||||
strcpy(cp, he->h_name);
|
||||
hptr->h_name = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* copy aliases */
|
||||
i = 0;
|
||||
hptr->h_aliases = hdptr->host_aliases;
|
||||
while (he->h_aliases[i] && i < (_MAXALIASES-1)) {
|
||||
if ((n = strlen(he->h_aliases[i]) + 1) < (eob - cp)) {
|
||||
strcpy(cp, he->h_aliases[i]);
|
||||
hptr->h_aliases[i] = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
hptr->h_aliases[i] = NULL;
|
||||
|
||||
return (HOST_R_OK);
|
||||
}
|
||||
#endif /* !HOSTENT_DATA */
|
||||
#else /* HOST_R_RETURN */
|
||||
static int gethostent_r_unknown_system = 0;
|
||||
#endif /* HOST_R_RETURN */
|
||||
#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
|
||||
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
* Issues to be discussed:
|
||||
* - Thread safe-ness must be checked
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by WIDE Project and
|
||||
* its contributors.
|
||||
* 4. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <port_before.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <port_after.h>
|
||||
|
||||
/*
|
||||
* Note that a_off will be dynamically adjusted so that to be consistent
|
||||
* with the definition of sockaddr_in{,6}.
|
||||
* The value presented below is just a guess.
|
||||
*/
|
||||
static struct afd {
|
||||
int a_af;
|
||||
int a_addrlen;
|
||||
size_t a_socklen;
|
||||
int a_off;
|
||||
} afdl [] = {
|
||||
/* first entry is linked last... */
|
||||
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
|
||||
offsetof(struct sockaddr_in, sin_addr)},
|
||||
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
|
||||
offsetof(struct sockaddr_in6, sin6_addr)},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
struct sockinet {
|
||||
#ifdef HAVE_SA_LEN
|
||||
u_char si_len;
|
||||
#endif
|
||||
u_char si_family;
|
||||
u_short si_port;
|
||||
};
|
||||
|
||||
static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *,
|
||||
size_t, int));
|
||||
#ifdef HAVE_SIN6_SCOPE_ID
|
||||
static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, int));
|
||||
#endif
|
||||
|
||||
int
|
||||
getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
|
||||
const struct sockaddr *sa;
|
||||
size_t salen;
|
||||
char *host;
|
||||
size_t hostlen;
|
||||
char *serv;
|
||||
size_t servlen;
|
||||
int flags;
|
||||
{
|
||||
struct afd *afd;
|
||||
struct servent *sp;
|
||||
struct hostent *hp;
|
||||
u_short port;
|
||||
#ifdef HAVE_SA_LEN
|
||||
size_t len;
|
||||
#endif
|
||||
int family, i;
|
||||
const char *addr;
|
||||
char *p;
|
||||
char numserv[512];
|
||||
char numaddr[512];
|
||||
const struct sockaddr_in6 *sin6;
|
||||
|
||||
if (sa == NULL)
|
||||
return EAI_FAIL;
|
||||
|
||||
#ifdef HAVE_SA_LEN
|
||||
len = sa->sa_len;
|
||||
if (len != salen) return EAI_FAIL;
|
||||
#endif
|
||||
|
||||
family = sa->sa_family;
|
||||
for (i = 0; afdl[i].a_af; i++)
|
||||
if (afdl[i].a_af == family) {
|
||||
afd = &afdl[i];
|
||||
goto found;
|
||||
}
|
||||
return EAI_FAMILY;
|
||||
|
||||
found:
|
||||
if (salen != afd->a_socklen) return EAI_FAIL;
|
||||
|
||||
port = ((const struct sockinet *)sa)->si_port; /* network byte order */
|
||||
addr = (const char *)sa + afd->a_off;
|
||||
|
||||
if (serv == NULL || servlen == 0U) {
|
||||
/*
|
||||
* rfc2553bis says that serv == NULL or servlen == 0 means that
|
||||
* the caller does not want the result.
|
||||
*/
|
||||
} else if (flags & NI_NUMERICSERV) {
|
||||
sprintf(numserv, "%d", ntohs(port));
|
||||
if (strlen(numserv) > servlen)
|
||||
return EAI_MEMORY;
|
||||
strcpy(serv, numserv);
|
||||
} else {
|
||||
sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
|
||||
if (sp) {
|
||||
if (strlen(sp->s_name) + 1 > servlen)
|
||||
return EAI_MEMORY;
|
||||
strcpy(serv, sp->s_name);
|
||||
} else
|
||||
return EAI_NONAME;
|
||||
}
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
if (ntohl(*(const u_int32_t *)addr) >> IN_CLASSA_NSHIFT == 0)
|
||||
flags |= NI_NUMERICHOST;
|
||||
break;
|
||||
case AF_INET6:
|
||||
sin6 = (const struct sockaddr_in6 *)sa;
|
||||
switch (sin6->sin6_addr.s6_addr[0]) {
|
||||
case 0x00:
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
|
||||
;
|
||||
else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
|
||||
;
|
||||
else
|
||||
flags |= NI_NUMERICHOST;
|
||||
break;
|
||||
default:
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
|
||||
flags |= NI_NUMERICHOST;
|
||||
else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
|
||||
flags |= NI_NUMERICHOST;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (host == NULL || hostlen == 0U) {
|
||||
/*
|
||||
* rfc2553bis says that host == NULL or hostlen == 0 means that
|
||||
* the caller does not want the result.
|
||||
*/
|
||||
} else if (flags & NI_NUMERICHOST) {
|
||||
goto numeric;
|
||||
} else {
|
||||
hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
|
||||
|
||||
if (hp) {
|
||||
if (flags & NI_NOFQDN) {
|
||||
p = strchr(hp->h_name, '.');
|
||||
if (p) *p = '\0';
|
||||
}
|
||||
if (strlen(hp->h_name) + 1 > hostlen)
|
||||
return EAI_MEMORY;
|
||||
strcpy(host, hp->h_name);
|
||||
} else {
|
||||
if (flags & NI_NAMEREQD)
|
||||
return EAI_NONAME;
|
||||
numeric:
|
||||
switch(afd->a_af) {
|
||||
case AF_INET6:
|
||||
{
|
||||
int error;
|
||||
|
||||
if ((error = ip6_parsenumeric(sa, addr, host,
|
||||
hostlen,
|
||||
flags)) != 0)
|
||||
return(error);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (inet_ntop(afd->a_af, addr, numaddr,
|
||||
sizeof(numaddr)) == NULL)
|
||||
return EAI_NONAME;
|
||||
if (strlen(numaddr) + 1 > hostlen)
|
||||
return EAI_MEMORY;
|
||||
strcpy(host, numaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host,
|
||||
size_t hostlen, int flags)
|
||||
{
|
||||
size_t numaddrlen;
|
||||
char numaddr[512];
|
||||
|
||||
#ifndef HAVE_SIN6_SCOPE_ID
|
||||
UNUSED(sa);
|
||||
UNUSED(flags);
|
||||
#endif
|
||||
|
||||
if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr))
|
||||
== NULL)
|
||||
return EAI_SYSTEM;
|
||||
|
||||
numaddrlen = strlen(numaddr);
|
||||
if (numaddrlen + 1 > hostlen) /* don't forget terminator */
|
||||
return EAI_MEMORY;
|
||||
strcpy(host, numaddr);
|
||||
|
||||
#ifdef HAVE_SIN6_SCOPE_ID
|
||||
if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
|
||||
char scopebuf[MAXHOSTNAMELEN]; /* XXX */
|
||||
int scopelen;
|
||||
|
||||
/* ip6_sa2str never fails */
|
||||
scopelen = ip6_sa2str((const struct sockaddr_in6 *)sa,
|
||||
scopebuf, sizeof(scopebuf), flags);
|
||||
|
||||
if (scopelen + 1 + numaddrlen + 1 > hostlen)
|
||||
return EAI_MEMORY;
|
||||
|
||||
/* construct <numeric-addr><delim><scopeid> */
|
||||
memcpy(host + numaddrlen + 1, scopebuf,
|
||||
scopelen);
|
||||
host[numaddrlen] = SCOPE_DELIMITER;
|
||||
host[numaddrlen + 1 + scopelen] = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIN6_SCOPE_ID
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf,
|
||||
size_t bufsiz, int flags)
|
||||
{
|
||||
#ifdef USE_IFNAMELINKID
|
||||
unsigned int ifindex = (unsigned int)sa6->sin6_scope_id;
|
||||
const struct in6_addr *a6 = &sa6->sin6_addr;
|
||||
#endif
|
||||
char tmp[64];
|
||||
|
||||
#ifdef NI_NUMERICSCOPE
|
||||
if (flags & NI_NUMERICSCOPE) {
|
||||
sprintf(tmp, "%u", sa6->sin6_scope_id);
|
||||
if (bufsiz != 0U) {
|
||||
strncpy(buf, tmp, bufsiz - 1);
|
||||
buf[bufsiz - 1] = '\0';
|
||||
}
|
||||
return(strlen(tmp));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_IFNAMELINKID
|
||||
/*
|
||||
* For a link-local address, convert the index to an interface
|
||||
* name, assuming a one-to-one mapping between links and interfaces.
|
||||
* Note, however, that this assumption is stronger than the
|
||||
* specification of the scoped address architecture; the
|
||||
* specficication says that more than one interfaces can belong to
|
||||
* a single link.
|
||||
*/
|
||||
|
||||
/* if_indextoname() does not take buffer size. not a good api... */
|
||||
if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
|
||||
bufsiz >= IF_NAMESIZE) {
|
||||
char *p = if_indextoname(ifindex, buf);
|
||||
if (p) {
|
||||
return(strlen(p));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* last resort */
|
||||
sprintf(tmp, "%u", sa6->sin6_scope_id);
|
||||
if (bufsiz != 0U) {
|
||||
strncpy(buf, tmp, bufsiz - 1);
|
||||
buf[bufsiz - 1] = '\0';
|
||||
}
|
||||
return(strlen(tmp));
|
||||
}
|
||||
#endif
|
||||
@@ -1,343 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#if !defined(__BIND_NOSTATIC)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "irs_data.h"
|
||||
|
||||
/* Definitions */
|
||||
|
||||
struct pvt {
|
||||
struct netent netent;
|
||||
char * aliases[1];
|
||||
char name[MAXDNAME + 1];
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static struct net_data *init(void);
|
||||
static struct netent *nw_to_net(struct nwent *, struct net_data *);
|
||||
static void freepvt(struct net_data *);
|
||||
static struct netent *fakeaddr(const char *, int af, struct net_data *);
|
||||
|
||||
/* Portability */
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
|
||||
/* Public */
|
||||
|
||||
struct netent *
|
||||
getnetent() {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getnetent_p(net_data));
|
||||
}
|
||||
|
||||
struct netent *
|
||||
getnetbyname(const char *name) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getnetbyname_p(name, net_data));
|
||||
}
|
||||
|
||||
struct netent *
|
||||
getnetbyaddr(unsigned long net, int type) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getnetbyaddr_p(net, type, net_data));
|
||||
}
|
||||
|
||||
void
|
||||
setnetent(int stayopen) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
setnetent_p(stayopen, net_data);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
endnetent() {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
endnetent_p(net_data);
|
||||
}
|
||||
|
||||
/* Shared private. */
|
||||
|
||||
struct netent *
|
||||
getnetent_p(struct net_data *net_data) {
|
||||
struct irs_nw *nw;
|
||||
|
||||
if (!net_data || !(nw = net_data->nw))
|
||||
return (NULL);
|
||||
net_data->nww_last = (*nw->next)(nw);
|
||||
net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
|
||||
return (net_data->nw_last);
|
||||
}
|
||||
|
||||
struct netent *
|
||||
getnetbyname_p(const char *name, struct net_data *net_data) {
|
||||
struct irs_nw *nw;
|
||||
struct netent *np;
|
||||
char **nap;
|
||||
|
||||
if (!net_data || !(nw = net_data->nw))
|
||||
return (NULL);
|
||||
if (net_data->nw_stayopen && net_data->nw_last) {
|
||||
if (!strcmp(net_data->nw_last->n_name, name))
|
||||
return (net_data->nw_last);
|
||||
for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++)
|
||||
if (!strcmp(name, *nap))
|
||||
return (net_data->nw_last);
|
||||
}
|
||||
if ((np = fakeaddr(name, AF_INET, net_data)) != NULL)
|
||||
return (np);
|
||||
net_data->nww_last = (*nw->byname)(nw, name, AF_INET);
|
||||
net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
|
||||
if (!net_data->nw_stayopen)
|
||||
endnetent();
|
||||
return (net_data->nw_last);
|
||||
}
|
||||
|
||||
struct netent *
|
||||
getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) {
|
||||
struct irs_nw *nw;
|
||||
u_char addr[4];
|
||||
int bits;
|
||||
|
||||
if (!net_data || !(nw = net_data->nw))
|
||||
return (NULL);
|
||||
if (net_data->nw_stayopen && net_data->nw_last)
|
||||
if (type == net_data->nw_last->n_addrtype &&
|
||||
net == net_data->nw_last->n_net)
|
||||
return (net_data->nw_last);
|
||||
|
||||
/* cannonize net(host order) */
|
||||
if (net < 256UL) {
|
||||
net <<= 24;
|
||||
bits = 8;
|
||||
} else if (net < 65536UL) {
|
||||
net <<= 16;
|
||||
bits = 16;
|
||||
} else if (net < 16777216UL) {
|
||||
net <<= 8;
|
||||
bits = 24;
|
||||
} else
|
||||
bits = 32;
|
||||
|
||||
/* convert to net order */
|
||||
addr[0] = (0xFF000000 & net) >> 24;
|
||||
addr[1] = (0x00FF0000 & net) >> 16;
|
||||
addr[2] = (0x0000FF00 & net) >> 8;
|
||||
addr[3] = (0x000000FF & net);
|
||||
|
||||
/* reduce bits to as close to natural number as possible */
|
||||
if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) {
|
||||
if ((addr[0] < 192) && (addr[2] == 0)) {
|
||||
if ((addr[0] < 128) && (addr[1] == 0))
|
||||
bits = 8;
|
||||
else
|
||||
bits = 16;
|
||||
} else {
|
||||
bits = 24;
|
||||
}
|
||||
}
|
||||
|
||||
net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET);
|
||||
net_data->nw_last = nw_to_net(net_data->nww_last, net_data);
|
||||
if (!net_data->nw_stayopen)
|
||||
endnetent();
|
||||
return (net_data->nw_last);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
setnetent_p(int stayopen, struct net_data *net_data) {
|
||||
struct irs_nw *nw;
|
||||
|
||||
if (!net_data || !(nw = net_data->nw))
|
||||
return;
|
||||
freepvt(net_data);
|
||||
(*nw->rewind)(nw);
|
||||
net_data->nw_stayopen = (stayopen != 0);
|
||||
if (stayopen == 0)
|
||||
net_data_minimize(net_data);
|
||||
}
|
||||
|
||||
void
|
||||
endnetent_p(struct net_data *net_data) {
|
||||
struct irs_nw *nw;
|
||||
|
||||
if ((net_data != NULL) && ((nw = net_data->nw) != NULL))
|
||||
(*nw->minimize)(nw);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
static struct net_data *
|
||||
init() {
|
||||
struct net_data *net_data;
|
||||
|
||||
if (!(net_data = net_data_init(NULL)))
|
||||
goto error;
|
||||
if (!net_data->nw) {
|
||||
net_data->nw = (*net_data->irs->nw_map)(net_data->irs);
|
||||
|
||||
if (!net_data->nw || !net_data->res) {
|
||||
error:
|
||||
errno = EIO;
|
||||
return (NULL);
|
||||
}
|
||||
(*net_data->nw->res_set)(net_data->nw, net_data->res, NULL);
|
||||
}
|
||||
|
||||
return (net_data);
|
||||
}
|
||||
|
||||
static void
|
||||
freepvt(struct net_data *net_data) {
|
||||
if (net_data->nw_data) {
|
||||
free(net_data->nw_data);
|
||||
net_data->nw_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct netent *
|
||||
fakeaddr(const char *name, int af, struct net_data *net_data) {
|
||||
struct pvt *pvt;
|
||||
const char *cp;
|
||||
u_long tmp;
|
||||
|
||||
if (af != AF_INET) {
|
||||
/* XXX should support IPv6 some day */
|
||||
errno = EAFNOSUPPORT;
|
||||
RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
if (!isascii((unsigned char)(name[0])) ||
|
||||
!isdigit((unsigned char)(name[0])))
|
||||
return (NULL);
|
||||
for (cp = name; *cp; ++cp)
|
||||
if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.'))
|
||||
return (NULL);
|
||||
if (*--cp == '.')
|
||||
return (NULL);
|
||||
|
||||
/* All-numeric, no dot at the end. */
|
||||
|
||||
tmp = inet_network(name);
|
||||
if (tmp == INADDR_NONE) {
|
||||
RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Valid network number specified.
|
||||
* Fake up a netent as if we'd actually
|
||||
* done a lookup.
|
||||
*/
|
||||
freepvt(net_data);
|
||||
net_data->nw_data = malloc(sizeof (struct pvt));
|
||||
if (!net_data->nw_data) {
|
||||
errno = ENOMEM;
|
||||
RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
pvt = net_data->nw_data;
|
||||
|
||||
strncpy(pvt->name, name, MAXDNAME);
|
||||
pvt->name[MAXDNAME] = '\0';
|
||||
pvt->netent.n_name = pvt->name;
|
||||
pvt->netent.n_addrtype = AF_INET;
|
||||
pvt->netent.n_aliases = pvt->aliases;
|
||||
pvt->aliases[0] = NULL;
|
||||
pvt->netent.n_net = tmp;
|
||||
|
||||
return (&pvt->netent);
|
||||
}
|
||||
|
||||
static struct netent *
|
||||
nw_to_net(struct nwent *nwent, struct net_data *net_data) {
|
||||
struct pvt *pvt;
|
||||
u_long addr = 0;
|
||||
int i;
|
||||
int msbyte;
|
||||
|
||||
if (!nwent || nwent->n_addrtype != AF_INET)
|
||||
return (NULL);
|
||||
freepvt(net_data);
|
||||
net_data->nw_data = malloc(sizeof (struct pvt));
|
||||
if (!net_data->nw_data) {
|
||||
errno = ENOMEM;
|
||||
RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
pvt = net_data->nw_data;
|
||||
pvt->netent.n_name = nwent->n_name;
|
||||
pvt->netent.n_aliases = nwent->n_aliases;
|
||||
pvt->netent.n_addrtype = nwent->n_addrtype;
|
||||
|
||||
/*
|
||||
* What this code does: Converts net addresses from network to host form.
|
||||
*
|
||||
* msbyte: the index of the most significant byte in the n_addr array.
|
||||
*
|
||||
* Shift bytes in significant order into addr. When all signicant
|
||||
* bytes are in, zero out bits in the LSB that are not part of the network.
|
||||
*/
|
||||
msbyte = nwent->n_length / 8 +
|
||||
((nwent->n_length % 8) != 0 ? 1 : 0) - 1;
|
||||
for (i = 0; i <= msbyte; i++)
|
||||
addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i];
|
||||
i = (32 - nwent->n_length) % 8;
|
||||
if (i != 0)
|
||||
addr &= ~((1 << (i + 1)) - 1);
|
||||
pvt->netent.n_net = addr;
|
||||
return (&pvt->netent);
|
||||
}
|
||||
|
||||
#endif /*__BIND_NOSTATIC*/
|
||||
@@ -1,227 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <port_before.h>
|
||||
#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
|
||||
static int getnetent_r_not_required = 0;
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/param.h>
|
||||
#include <port_after.h>
|
||||
|
||||
#ifdef NET_R_RETURN
|
||||
|
||||
static NET_R_RETURN
|
||||
copy_netent(struct netent *, struct netent *, NET_R_COPY_ARGS);
|
||||
|
||||
NET_R_RETURN
|
||||
getnetbyname_r(const char *name, struct netent *nptr, NET_R_ARGS) {
|
||||
struct netent *ne = getnetbyname(name);
|
||||
#ifdef NET_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = ne;
|
||||
if (ne == NULL)
|
||||
*h_errnop = h_errno;
|
||||
return (n);
|
||||
#else
|
||||
if (ne == NULL)
|
||||
return (NET_R_BAD);
|
||||
|
||||
return (copy_netent(ne, nptr, NET_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef GETNETBYADDR_ADDR_T
|
||||
#define GETNETBYADDR_ADDR_T long
|
||||
#endif
|
||||
NET_R_RETURN
|
||||
getnetbyaddr_r(GETNETBYADDR_ADDR_T addr, int type, struct netent *nptr, NET_R_ARGS) {
|
||||
struct netent *ne = getnetbyaddr(addr, type);
|
||||
#ifdef NET_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = ne;
|
||||
if (ne == NULL)
|
||||
*h_errnop = h_errno;
|
||||
return (n);
|
||||
#else
|
||||
|
||||
if (ne == NULL)
|
||||
return (NET_R_BAD);
|
||||
|
||||
return (copy_netent(ne, nptr, NET_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* These assume a single context is in operation per thread.
|
||||
* If this is not the case we will need to call irs directly
|
||||
* rather than through the base functions.
|
||||
*/
|
||||
|
||||
NET_R_RETURN
|
||||
getnetent_r(struct netent *nptr, NET_R_ARGS) {
|
||||
struct netent *ne = getnetent();
|
||||
#ifdef NET_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = ne;
|
||||
if (ne == NULL)
|
||||
*h_errnop = h_errno;
|
||||
return (n);
|
||||
#else
|
||||
|
||||
if (ne == NULL)
|
||||
return (NET_R_BAD);
|
||||
|
||||
return (copy_netent(ne, nptr, NET_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
NET_R_SET_RETURN
|
||||
#ifdef NET_R_ENT_ARGS
|
||||
setnetent_r(int stay_open, NET_R_ENT_ARGS)
|
||||
#else
|
||||
setnetent_r(int stay_open)
|
||||
#endif
|
||||
{
|
||||
setnetent(stay_open);
|
||||
#ifdef NET_R_SET_RESULT
|
||||
return (NET_R_SET_RESULT);
|
||||
#endif
|
||||
}
|
||||
|
||||
NET_R_END_RETURN
|
||||
#ifdef NET_R_ENT_ARGS
|
||||
endnetent_r(NET_R_ENT_ARGS)
|
||||
#else
|
||||
endnetent_r()
|
||||
#endif
|
||||
{
|
||||
endnetent();
|
||||
NET_R_END_RESULT(NET_R_OK);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
#ifndef NETENT_DATA
|
||||
static NET_R_RETURN
|
||||
copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) {
|
||||
char *cp;
|
||||
int i, n;
|
||||
int numptr, len;
|
||||
|
||||
/* Find out the amount of space required to store the answer. */
|
||||
numptr = 1; /* NULL ptr */
|
||||
len = (char *)ALIGN(buf) - buf;
|
||||
for (i = 0; ne->n_aliases[i]; i++, numptr++) {
|
||||
len += strlen(ne->n_aliases[i]) + 1;
|
||||
}
|
||||
len += strlen(ne->n_name) + 1;
|
||||
len += numptr * sizeof(char*);
|
||||
|
||||
if (len > (int)buflen) {
|
||||
errno = ERANGE;
|
||||
return (NET_R_BAD);
|
||||
}
|
||||
|
||||
/* copy net value and type */
|
||||
nptr->n_addrtype = ne->n_addrtype;
|
||||
nptr->n_net = ne->n_net;
|
||||
|
||||
cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
|
||||
|
||||
/* copy official name */
|
||||
n = strlen(ne->n_name) + 1;
|
||||
strcpy(cp, ne->n_name);
|
||||
nptr->n_name = cp;
|
||||
cp += n;
|
||||
|
||||
/* copy aliases */
|
||||
nptr->n_aliases = (char **)ALIGN(buf);
|
||||
for (i = 0 ; ne->n_aliases[i]; i++) {
|
||||
n = strlen(ne->n_aliases[i]) + 1;
|
||||
strcpy(cp, ne->n_aliases[i]);
|
||||
nptr->n_aliases[i] = cp;
|
||||
cp += n;
|
||||
}
|
||||
nptr->n_aliases[i] = NULL;
|
||||
|
||||
return (NET_R_OK);
|
||||
}
|
||||
#else /* !NETENT_DATA */
|
||||
static int
|
||||
copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) {
|
||||
char *cp, *eob;
|
||||
int i, n;
|
||||
|
||||
/* copy net value and type */
|
||||
nptr->n_addrtype = ne->n_addrtype;
|
||||
nptr->n_net = ne->n_net;
|
||||
|
||||
/* copy official name */
|
||||
cp = ndptr->line;
|
||||
eob = ndptr->line + sizeof(ndptr->line);
|
||||
if ((n = strlen(ne->n_name) + 1) < (eob - cp)) {
|
||||
strcpy(cp, ne->n_name);
|
||||
nptr->n_name = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* copy aliases */
|
||||
i = 0;
|
||||
nptr->n_aliases = ndptr->net_aliases;
|
||||
while (ne->n_aliases[i] && i < (_MAXALIASES-1)) {
|
||||
if ((n = strlen(ne->n_aliases[i]) + 1) < (eob - cp)) {
|
||||
strcpy(cp, ne->n_aliases[i]);
|
||||
nptr->n_aliases[i] = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
nptr->n_aliases[i] = NULL;
|
||||
|
||||
return (NET_R_OK);
|
||||
}
|
||||
#endif /* !NETENT_DATA */
|
||||
#else /* NET_R_RETURN */
|
||||
static int getnetent_r_unknown_system = 0;
|
||||
#endif /* NET_R_RETURN */
|
||||
#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#if !defined(__BIND_NOSTATIC)
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_data.h"
|
||||
|
||||
/* Forward */
|
||||
|
||||
static struct net_data *init(void);
|
||||
|
||||
|
||||
/* Public */
|
||||
|
||||
#ifndef SETNETGRENT_ARGS
|
||||
#define SETNETGRENT_ARGS const char *netgroup
|
||||
#endif
|
||||
void
|
||||
setnetgrent(SETNETGRENT_ARGS) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
setnetgrent_p(netgroup, net_data);
|
||||
}
|
||||
|
||||
void
|
||||
endnetgrent(void) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
endnetgrent_p(net_data);
|
||||
}
|
||||
|
||||
#ifndef INNETGR_ARGS
|
||||
#define INNETGR_ARGS const char *netgroup, const char *host, \
|
||||
const char *user, const char *domain
|
||||
#endif
|
||||
int
|
||||
innetgr(INNETGR_ARGS) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (innetgr_p(netgroup, host, user, domain, net_data));
|
||||
}
|
||||
|
||||
int
|
||||
getnetgrent(char **host, char **user, char **domain) {
|
||||
struct net_data *net_data = init();
|
||||
const char *ch, *cu, *cd;
|
||||
int ret;
|
||||
|
||||
ret = getnetgrent_p(&ch, &cu, &cd, net_data);
|
||||
if (ret != 1)
|
||||
return (ret);
|
||||
|
||||
DE_CONST(ch, *host);
|
||||
DE_CONST(cu, *user);
|
||||
DE_CONST(cd, *domain);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Shared private. */
|
||||
|
||||
void
|
||||
setnetgrent_p(const char *netgroup, struct net_data *net_data) {
|
||||
struct irs_ng *ng;
|
||||
|
||||
if ((net_data != NULL) && ((ng = net_data->ng) != NULL))
|
||||
(*ng->rewind)(ng, netgroup);
|
||||
}
|
||||
|
||||
void
|
||||
endnetgrent_p(struct net_data *net_data) {
|
||||
struct irs_ng *ng;
|
||||
|
||||
if (!net_data)
|
||||
return;
|
||||
if ((ng = net_data->ng) != NULL)
|
||||
(*ng->close)(ng);
|
||||
net_data->ng = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
innetgr_p(const char *netgroup, const char *host,
|
||||
const char *user, const char *domain,
|
||||
struct net_data *net_data) {
|
||||
struct irs_ng *ng;
|
||||
|
||||
if (!net_data || !(ng = net_data->ng))
|
||||
return (0);
|
||||
return ((*ng->test)(ng, netgroup, host, user, domain));
|
||||
}
|
||||
|
||||
int
|
||||
getnetgrent_p(const char **host, const char **user, const char **domain,
|
||||
struct net_data *net_data ) {
|
||||
struct irs_ng *ng;
|
||||
|
||||
if (!net_data || !(ng = net_data->ng))
|
||||
return (0);
|
||||
return ((*ng->next)(ng, host, user, domain));
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
static struct net_data *
|
||||
init(void) {
|
||||
struct net_data *net_data;
|
||||
|
||||
if (!(net_data = net_data_init(NULL)))
|
||||
goto error;
|
||||
if (!net_data->ng) {
|
||||
net_data->ng = (*net_data->irs->ng_map)(net_data->irs);
|
||||
if (!net_data->ng) {
|
||||
error:
|
||||
errno = EIO;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (net_data);
|
||||
}
|
||||
|
||||
#endif /*__BIND_NOSTATIC*/
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <port_before.h>
|
||||
#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
|
||||
static int getnetgrent_r_not_required = 0;
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <port_after.h>
|
||||
|
||||
#ifdef NGR_R_RETURN
|
||||
|
||||
static NGR_R_RETURN
|
||||
copy_protoent(char **, char **, char **, const char *, const char *,
|
||||
const char *, NGR_R_COPY_ARGS);
|
||||
|
||||
NGR_R_RETURN
|
||||
innetgr_r(const char *netgroup, const char *host, const char *user,
|
||||
const char *domain) {
|
||||
char *ng, *ho, *us, *dom;
|
||||
|
||||
DE_CONST(netgroup, ng);
|
||||
DE_CONST(host, ho);
|
||||
DE_CONST(user, us);
|
||||
DE_CONST(domain, dom);
|
||||
|
||||
return (innetgr(ng, ho, us, dom));
|
||||
}
|
||||
|
||||
/*
|
||||
* These assume a single context is in operation per thread.
|
||||
* If this is not the case we will need to call irs directly
|
||||
* rather than through the base functions.
|
||||
*/
|
||||
|
||||
NGR_R_RETURN
|
||||
getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS) {
|
||||
char *mp, *up, *dp;
|
||||
int res = getnetgrent(&mp, &up, &dp);
|
||||
|
||||
if (res != 1)
|
||||
return (res);
|
||||
|
||||
return (copy_protoent(machinep, userp, domainp,
|
||||
mp, up, dp, NGR_R_COPY));
|
||||
}
|
||||
|
||||
NGR_R_SET_RETURN
|
||||
#ifdef NGR_R_ENT_ARGS
|
||||
setnetgrent_r(const char *netgroup, NGR_R_ENT_ARGS)
|
||||
#else
|
||||
setnetgrent_r(const char *netgroup)
|
||||
#endif
|
||||
{
|
||||
char *tmp;
|
||||
DE_CONST(netgroup, tmp);
|
||||
setnetgrent(tmp);
|
||||
#ifdef NGR_R_PRIVATE
|
||||
*buf = NULL;
|
||||
#endif
|
||||
#ifdef NGR_R_SET_RESULT
|
||||
return (NGR_R_SET_RESULT);
|
||||
#endif
|
||||
}
|
||||
|
||||
NGR_R_END_RETURN
|
||||
#ifdef NGR_R_ENT_ARGS
|
||||
endnetgrent_r(NGR_R_ENT_ARGS)
|
||||
#else
|
||||
endnetgrent_r(void)
|
||||
#endif
|
||||
{
|
||||
endnetgrent();
|
||||
#ifdef NGR_R_PRIVATE
|
||||
if (*buf != NULL)
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
#endif
|
||||
NGR_R_END_RESULT(NGR_R_OK);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
static int
|
||||
copy_protoent(char **machinep, char **userp, char **domainp,
|
||||
const char *mp, const char *up, const char *dp,
|
||||
NGR_R_COPY_ARGS) {
|
||||
char *cp;
|
||||
int n;
|
||||
int len;
|
||||
|
||||
/* Find out the amount of space required to store the answer. */
|
||||
len = 0;
|
||||
if (mp != NULL) len += strlen(mp) + 1;
|
||||
if (up != NULL) len += strlen(up) + 1;
|
||||
if (dp != NULL) len += strlen(dp) + 1;
|
||||
|
||||
#ifdef NGR_R_PRIVATE
|
||||
free(*buf);
|
||||
*buf = malloc(len);
|
||||
if (*buf == NULL)
|
||||
return(NGR_R_BAD);
|
||||
cp = *buf;
|
||||
#else
|
||||
if (len > (int)buflen) {
|
||||
errno = ERANGE;
|
||||
return (NGR_R_BAD);
|
||||
}
|
||||
cp = buf;
|
||||
#endif
|
||||
|
||||
|
||||
if (mp != NULL) {
|
||||
n = strlen(mp) + 1;
|
||||
strcpy(cp, mp);
|
||||
*machinep = cp;
|
||||
cp += n;
|
||||
} else
|
||||
*machinep = NULL;
|
||||
|
||||
if (up != NULL) {
|
||||
n = strlen(up) + 1;
|
||||
strcpy(cp, up);
|
||||
*userp = cp;
|
||||
cp += n;
|
||||
} else
|
||||
*userp = NULL;
|
||||
|
||||
if (dp != NULL) {
|
||||
n = strlen(dp) + 1;
|
||||
strcpy(cp, dp);
|
||||
*domainp = cp;
|
||||
cp += n;
|
||||
} else
|
||||
*domainp = NULL;
|
||||
|
||||
return (NGR_R_OK);
|
||||
}
|
||||
#else /* NGR_R_RETURN */
|
||||
static int getnetgrent_r_unknown_system = 0;
|
||||
#endif /* NGR_R_RETURN */
|
||||
#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#if !defined(__BIND_NOSTATIC)
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_data.h"
|
||||
|
||||
/* Forward */
|
||||
|
||||
static struct net_data *init(void);
|
||||
|
||||
/* Public */
|
||||
|
||||
struct protoent *
|
||||
getprotoent() {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getprotoent_p(net_data));
|
||||
}
|
||||
|
||||
struct protoent *
|
||||
getprotobyname(const char *name) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getprotobyname_p(name, net_data));
|
||||
}
|
||||
|
||||
struct protoent *
|
||||
getprotobynumber(int proto) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getprotobynumber_p(proto, net_data));
|
||||
}
|
||||
|
||||
void
|
||||
setprotoent(int stayopen) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
setprotoent_p(stayopen, net_data);
|
||||
}
|
||||
|
||||
void
|
||||
endprotoent() {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
endprotoent_p(net_data);
|
||||
}
|
||||
|
||||
/* Shared private. */
|
||||
|
||||
struct protoent *
|
||||
getprotoent_p(struct net_data *net_data) {
|
||||
struct irs_pr *pr;
|
||||
|
||||
if (!net_data || !(pr = net_data->pr))
|
||||
return (NULL);
|
||||
net_data->pr_last = (*pr->next)(pr);
|
||||
return (net_data->pr_last);
|
||||
}
|
||||
|
||||
struct protoent *
|
||||
getprotobyname_p(const char *name, struct net_data *net_data) {
|
||||
struct irs_pr *pr;
|
||||
char **pap;
|
||||
|
||||
if (!net_data || !(pr = net_data->pr))
|
||||
return (NULL);
|
||||
if (net_data->pr_stayopen && net_data->pr_last) {
|
||||
if (!strcmp(net_data->pr_last->p_name, name))
|
||||
return (net_data->pr_last);
|
||||
for (pap = net_data->pr_last->p_aliases; pap && *pap; pap++)
|
||||
if (!strcmp(name, *pap))
|
||||
return (net_data->pr_last);
|
||||
}
|
||||
net_data->pr_last = (*pr->byname)(pr, name);
|
||||
if (!net_data->pr_stayopen)
|
||||
endprotoent();
|
||||
return (net_data->pr_last);
|
||||
}
|
||||
|
||||
struct protoent *
|
||||
getprotobynumber_p(int proto, struct net_data *net_data) {
|
||||
struct irs_pr *pr;
|
||||
|
||||
if (!net_data || !(pr = net_data->pr))
|
||||
return (NULL);
|
||||
if (net_data->pr_stayopen && net_data->pr_last)
|
||||
if (net_data->pr_last->p_proto == proto)
|
||||
return (net_data->pr_last);
|
||||
net_data->pr_last = (*pr->bynumber)(pr, proto);
|
||||
if (!net_data->pr_stayopen)
|
||||
endprotoent();
|
||||
return (net_data->pr_last);
|
||||
}
|
||||
|
||||
void
|
||||
setprotoent_p(int stayopen, struct net_data *net_data) {
|
||||
struct irs_pr *pr;
|
||||
|
||||
if (!net_data || !(pr = net_data->pr))
|
||||
return;
|
||||
(*pr->rewind)(pr);
|
||||
net_data->pr_stayopen = (stayopen != 0);
|
||||
if (stayopen == 0)
|
||||
net_data_minimize(net_data);
|
||||
}
|
||||
|
||||
void
|
||||
endprotoent_p(struct net_data *net_data) {
|
||||
struct irs_pr *pr;
|
||||
|
||||
if ((net_data != NULL) && ((pr = net_data->pr) != NULL))
|
||||
(*pr->minimize)(pr);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
static struct net_data *
|
||||
init() {
|
||||
struct net_data *net_data;
|
||||
|
||||
if (!(net_data = net_data_init(NULL)))
|
||||
goto error;
|
||||
if (!net_data->pr) {
|
||||
net_data->pr = (*net_data->irs->pr_map)(net_data->irs);
|
||||
|
||||
if (!net_data->pr || !net_data->res) {
|
||||
error:
|
||||
errno = EIO;
|
||||
return (NULL);
|
||||
}
|
||||
(*net_data->pr->res_set)(net_data->pr, net_data->res, NULL);
|
||||
}
|
||||
|
||||
return (net_data);
|
||||
}
|
||||
|
||||
#endif /*__BIND_NOSTATIC*/
|
||||
@@ -1,216 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <port_before.h>
|
||||
#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
|
||||
static int getprotoent_r_not_required = 0;
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <port_after.h>
|
||||
|
||||
#ifdef PROTO_R_RETURN
|
||||
|
||||
static PROTO_R_RETURN
|
||||
copy_protoent(struct protoent *, struct protoent *, PROTO_R_COPY_ARGS);
|
||||
|
||||
PROTO_R_RETURN
|
||||
getprotobyname_r(const char *name, struct protoent *pptr, PROTO_R_ARGS) {
|
||||
struct protoent *pe = getprotobyname(name);
|
||||
#ifdef PROTO_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = pptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (pe == NULL)
|
||||
return (PROTO_R_BAD);
|
||||
|
||||
return (copy_protoent(pe, pptr, PROTO_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
PROTO_R_RETURN
|
||||
getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) {
|
||||
struct protoent *pe = getprotobynumber(proto);
|
||||
#ifdef PROTO_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = pptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (pe == NULL)
|
||||
return (PROTO_R_BAD);
|
||||
|
||||
return (copy_protoent(pe, pptr, PROTO_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* These assume a single context is in operation per thread.
|
||||
* If this is not the case we will need to call irs directly
|
||||
* rather than through the base functions.
|
||||
*/
|
||||
|
||||
PROTO_R_RETURN
|
||||
getprotoent_r(struct protoent *pptr, PROTO_R_ARGS) {
|
||||
struct protoent *pe = getprotoent();
|
||||
#ifdef PROTO_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = pptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (pe == NULL)
|
||||
return (PROTO_R_BAD);
|
||||
|
||||
return (copy_protoent(pe, pptr, PROTO_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
PROTO_R_SET_RETURN
|
||||
#ifdef PROTO_R_ENT_ARGS
|
||||
setprotoent_r(int stay_open, PROTO_R_ENT_ARGS)
|
||||
#else
|
||||
setprotoent_r(int stay_open)
|
||||
#endif
|
||||
{
|
||||
setprotoent(stay_open);
|
||||
#ifdef PROTO_R_SET_RESULT
|
||||
return (PROTO_R_SET_RESULT);
|
||||
#endif
|
||||
}
|
||||
|
||||
PROTO_R_END_RETURN
|
||||
#ifdef PROTO_R_ENT_ARGS
|
||||
endprotoent_r(PROTO_R_ENT_ARGS)
|
||||
#else
|
||||
endprotoent_r()
|
||||
#endif
|
||||
{
|
||||
endprotoent();
|
||||
PROTO_R_END_RESULT(PROTO_R_OK);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
#ifndef PROTOENT_DATA
|
||||
static PROTO_R_RETURN
|
||||
copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) {
|
||||
char *cp;
|
||||
int i, n;
|
||||
int numptr, len;
|
||||
|
||||
/* Find out the amount of space required to store the answer. */
|
||||
numptr = 1; /* NULL ptr */
|
||||
len = (char *)ALIGN(buf) - buf;
|
||||
for (i = 0; pe->p_aliases[i]; i++, numptr++) {
|
||||
len += strlen(pe->p_aliases[i]) + 1;
|
||||
}
|
||||
len += strlen(pe->p_name) + 1;
|
||||
len += numptr * sizeof(char*);
|
||||
|
||||
if (len > (int)buflen) {
|
||||
errno = ERANGE;
|
||||
return (PROTO_R_BAD);
|
||||
}
|
||||
|
||||
/* copy protocol value*/
|
||||
pptr->p_proto = pe->p_proto;
|
||||
|
||||
cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
|
||||
|
||||
/* copy official name */
|
||||
n = strlen(pe->p_name) + 1;
|
||||
strcpy(cp, pe->p_name);
|
||||
pptr->p_name = cp;
|
||||
cp += n;
|
||||
|
||||
/* copy aliases */
|
||||
pptr->p_aliases = (char **)ALIGN(buf);
|
||||
for (i = 0 ; pe->p_aliases[i]; i++) {
|
||||
n = strlen(pe->p_aliases[i]) + 1;
|
||||
strcpy(cp, pe->p_aliases[i]);
|
||||
pptr->p_aliases[i] = cp;
|
||||
cp += n;
|
||||
}
|
||||
pptr->p_aliases[i] = NULL;
|
||||
|
||||
return (PROTO_R_OK);
|
||||
}
|
||||
#else /* !PROTOENT_DATA */
|
||||
static int
|
||||
copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) {
|
||||
char *cp, *eob;
|
||||
int i, n;
|
||||
|
||||
/* copy protocol value */
|
||||
pptr->p_proto = pe->p_proto;
|
||||
|
||||
/* copy official name */
|
||||
cp = pdptr->line;
|
||||
eob = pdptr->line + sizeof(pdptr->line);
|
||||
if ((n = strlen(pe->p_name) + 1) < (eob - cp)) {
|
||||
strcpy(cp, pe->p_name);
|
||||
pptr->p_name = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* copy aliases */
|
||||
i = 0;
|
||||
pptr->p_aliases = pdptr->proto_aliases;
|
||||
while (pe->p_aliases[i] && i < (_MAXALIASES-1)) {
|
||||
if ((n = strlen(pe->p_aliases[i]) + 1) < (eob - cp)) {
|
||||
strcpy(cp, pe->p_aliases[i]);
|
||||
pptr->p_aliases[i] = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
pptr->p_aliases[i] = NULL;
|
||||
|
||||
return (PROTO_R_OK);
|
||||
}
|
||||
#endif /* PROTOENT_DATA */
|
||||
#else /* PROTO_R_RETURN */
|
||||
static int getprotoent_r_unknown_system = 0;
|
||||
#endif /* PROTO_R_RETURN */
|
||||
#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#if !defined(__BIND_NOSTATIC)
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_data.h"
|
||||
|
||||
/* Forward */
|
||||
|
||||
static struct net_data *init(void);
|
||||
|
||||
/* Public */
|
||||
|
||||
struct servent *
|
||||
getservent(void) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getservent_p(net_data));
|
||||
}
|
||||
|
||||
struct servent *
|
||||
getservbyname(const char *name, const char *proto) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getservbyname_p(name, proto, net_data));
|
||||
}
|
||||
|
||||
struct servent *
|
||||
getservbyport(int port, const char *proto) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
return (getservbyport_p(port, proto, net_data));
|
||||
}
|
||||
|
||||
void
|
||||
setservent(int stayopen) {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
setservent_p(stayopen, net_data);
|
||||
}
|
||||
|
||||
void
|
||||
endservent() {
|
||||
struct net_data *net_data = init();
|
||||
|
||||
endservent_p(net_data);
|
||||
}
|
||||
|
||||
/* Shared private. */
|
||||
|
||||
struct servent *
|
||||
getservent_p(struct net_data *net_data) {
|
||||
struct irs_sv *sv;
|
||||
|
||||
if (!net_data || !(sv = net_data->sv))
|
||||
return (NULL);
|
||||
net_data->sv_last = (*sv->next)(sv);
|
||||
return (net_data->sv_last);
|
||||
}
|
||||
|
||||
struct servent *
|
||||
getservbyname_p(const char *name, const char *proto,
|
||||
struct net_data *net_data) {
|
||||
struct irs_sv *sv;
|
||||
char **sap;
|
||||
|
||||
if (!net_data || !(sv = net_data->sv))
|
||||
return (NULL);
|
||||
if (net_data->sv_stayopen && net_data->sv_last)
|
||||
if (!proto || !strcmp(net_data->sv_last->s_proto, proto)) {
|
||||
if (!strcmp(net_data->sv_last->s_name, name))
|
||||
return (net_data->sv_last);
|
||||
for (sap = net_data->sv_last->s_aliases;
|
||||
sap && *sap; sap++)
|
||||
if (!strcmp(name, *sap))
|
||||
return (net_data->sv_last);
|
||||
}
|
||||
net_data->sv_last = (*sv->byname)(sv, name, proto);
|
||||
if (!net_data->sv_stayopen)
|
||||
endservent();
|
||||
return (net_data->sv_last);
|
||||
}
|
||||
|
||||
struct servent *
|
||||
getservbyport_p(int port, const char *proto, struct net_data *net_data) {
|
||||
struct irs_sv *sv;
|
||||
|
||||
if (!net_data || !(sv = net_data->sv))
|
||||
return (NULL);
|
||||
if (net_data->sv_stayopen && net_data->sv_last)
|
||||
if (port == net_data->sv_last->s_port &&
|
||||
( !proto ||
|
||||
!strcmp(net_data->sv_last->s_proto, proto)))
|
||||
return (net_data->sv_last);
|
||||
net_data->sv_last = (*sv->byport)(sv, port, proto);
|
||||
return (net_data->sv_last);
|
||||
}
|
||||
|
||||
void
|
||||
setservent_p(int stayopen, struct net_data *net_data) {
|
||||
struct irs_sv *sv;
|
||||
|
||||
if (!net_data || !(sv = net_data->sv))
|
||||
return;
|
||||
(*sv->rewind)(sv);
|
||||
net_data->sv_stayopen = (stayopen != 0);
|
||||
if (stayopen == 0)
|
||||
net_data_minimize(net_data);
|
||||
}
|
||||
|
||||
void
|
||||
endservent_p(struct net_data *net_data) {
|
||||
struct irs_sv *sv;
|
||||
|
||||
if ((net_data != NULL) && ((sv = net_data->sv) != NULL))
|
||||
(*sv->minimize)(sv);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
static struct net_data *
|
||||
init() {
|
||||
struct net_data *net_data;
|
||||
|
||||
if (!(net_data = net_data_init(NULL)))
|
||||
goto error;
|
||||
if (!net_data->sv) {
|
||||
net_data->sv = (*net_data->irs->sv_map)(net_data->irs);
|
||||
|
||||
if (!net_data->sv || !net_data->res) {
|
||||
error:
|
||||
errno = EIO;
|
||||
return (NULL);
|
||||
}
|
||||
(*net_data->sv->res_set)(net_data->sv, net_data->res, NULL);
|
||||
}
|
||||
|
||||
return (net_data);
|
||||
}
|
||||
|
||||
#endif /*__BIND_NOSTATIC*/
|
||||
@@ -1,237 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <port_before.h>
|
||||
#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
|
||||
static int getservent_r_not_required = 0;
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/param.h>
|
||||
#include <port_after.h>
|
||||
|
||||
#ifdef SERV_R_RETURN
|
||||
|
||||
static SERV_R_RETURN
|
||||
copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS);
|
||||
|
||||
SERV_R_RETURN
|
||||
getservbyname_r(const char *name, const char *proto,
|
||||
struct servent *sptr, SERV_R_ARGS) {
|
||||
struct servent *se = getservbyname(name, proto);
|
||||
#ifdef SERV_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = sptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (se == NULL)
|
||||
return (SERV_R_BAD);
|
||||
|
||||
return (copy_servent(se, sptr, SERV_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
SERV_R_RETURN
|
||||
getservbyport_r(int port, const char *proto,
|
||||
struct servent *sptr, SERV_R_ARGS) {
|
||||
struct servent *se = getservbyport(port, proto);
|
||||
#ifdef SERV_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = sptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (se == NULL)
|
||||
return (SERV_R_BAD);
|
||||
|
||||
return (copy_servent(se, sptr, SERV_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* These assume a single context is in operation per thread.
|
||||
* If this is not the case we will need to call irs directly
|
||||
* rather than through the base functions.
|
||||
*/
|
||||
|
||||
SERV_R_RETURN
|
||||
getservent_r(struct servent *sptr, SERV_R_ARGS) {
|
||||
struct servent *se = getservent();
|
||||
#ifdef SERV_R_SETANSWER
|
||||
int n = 0;
|
||||
|
||||
if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
|
||||
*answerp = NULL;
|
||||
else
|
||||
*answerp = sptr;
|
||||
|
||||
return (n);
|
||||
#else
|
||||
if (se == NULL)
|
||||
return (SERV_R_BAD);
|
||||
|
||||
return (copy_servent(se, sptr, SERV_R_COPY));
|
||||
#endif
|
||||
}
|
||||
|
||||
SERV_R_SET_RETURN
|
||||
#ifdef SERV_R_ENT_ARGS
|
||||
setservent_r(int stay_open, SERV_R_ENT_ARGS)
|
||||
#else
|
||||
setservent_r(int stay_open)
|
||||
#endif
|
||||
{
|
||||
|
||||
setservent(stay_open);
|
||||
#ifdef SERV_R_SET_RESULT
|
||||
return (SERV_R_SET_RESULT);
|
||||
#endif
|
||||
}
|
||||
|
||||
SERV_R_END_RETURN
|
||||
#ifdef SERV_R_ENT_ARGS
|
||||
endservent_r(SERV_R_ENT_ARGS)
|
||||
#else
|
||||
endservent_r()
|
||||
#endif
|
||||
{
|
||||
|
||||
endservent();
|
||||
SERV_R_END_RESULT(SERV_R_OK);
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
#ifndef SERVENT_DATA
|
||||
static SERV_R_RETURN
|
||||
copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) {
|
||||
char *cp;
|
||||
int i, n;
|
||||
int numptr, len;
|
||||
|
||||
/* Find out the amount of space required to store the answer. */
|
||||
numptr = 1; /* NULL ptr */
|
||||
len = (char *)ALIGN(buf) - buf;
|
||||
for (i = 0; se->s_aliases[i]; i++, numptr++) {
|
||||
len += strlen(se->s_aliases[i]) + 1;
|
||||
}
|
||||
len += strlen(se->s_name) + 1;
|
||||
len += strlen(se->s_proto) + 1;
|
||||
len += numptr * sizeof(char*);
|
||||
|
||||
if (len > (int)buflen) {
|
||||
errno = ERANGE;
|
||||
return (SERV_R_BAD);
|
||||
}
|
||||
|
||||
/* copy port value */
|
||||
sptr->s_port = se->s_port;
|
||||
|
||||
cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
|
||||
|
||||
/* copy official name */
|
||||
n = strlen(se->s_name) + 1;
|
||||
strcpy(cp, se->s_name);
|
||||
sptr->s_name = cp;
|
||||
cp += n;
|
||||
|
||||
/* copy aliases */
|
||||
sptr->s_aliases = (char **)ALIGN(buf);
|
||||
for (i = 0 ; se->s_aliases[i]; i++) {
|
||||
n = strlen(se->s_aliases[i]) + 1;
|
||||
strcpy(cp, se->s_aliases[i]);
|
||||
sptr->s_aliases[i] = cp;
|
||||
cp += n;
|
||||
}
|
||||
sptr->s_aliases[i] = NULL;
|
||||
|
||||
/* copy proto */
|
||||
n = strlen(se->s_proto) + 1;
|
||||
strcpy(cp, se->s_proto);
|
||||
sptr->s_proto = cp;
|
||||
cp += n;
|
||||
|
||||
return (SERV_R_OK);
|
||||
}
|
||||
#else /* !SERVENT_DATA */
|
||||
static int
|
||||
copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) {
|
||||
char *cp, *eob;
|
||||
int i, n;
|
||||
|
||||
/* copy port value */
|
||||
sptr->s_port = se->s_port;
|
||||
|
||||
/* copy official name */
|
||||
cp = ndptr->line;
|
||||
eob = ndptr->line + sizeof(ndptr->line);
|
||||
if ((n = strlen(se->s_name) + 1) < (eob - cp)) {
|
||||
strcpy(cp, se->s_name);
|
||||
sptr->s_name = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* copy aliases */
|
||||
i = 0;
|
||||
sptr->s_aliases = ndptr->serv_aliases;
|
||||
while (se->s_aliases[i] && i < (_MAXALIASES-1)) {
|
||||
if ((n = strlen(se->s_aliases[i]) + 1) < (eob - cp)) {
|
||||
strcpy(cp, se->s_aliases[i]);
|
||||
sptr->s_aliases[i] = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
sptr->s_aliases[i] = NULL;
|
||||
|
||||
/* copy proto */
|
||||
if ((n = strlen(se->s_proto) + 1) < (eob - cp)) {
|
||||
strcpy(cp, se->s_proto);
|
||||
sptr->s_proto = cp;
|
||||
cp += n;
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (SERV_R_OK);
|
||||
}
|
||||
#endif /* !SERVENT_DATA */
|
||||
#else /*SERV_R_RETURN */
|
||||
static int getservent_r_unknown_system = 0;
|
||||
#endif /*SERV_R_RETURN */
|
||||
#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
|
||||
@@ -1,507 +0,0 @@
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* hesiod.c --- the core portion of the hesiod resolver.
|
||||
*
|
||||
* This file is derived from the hesiod library from Project Athena;
|
||||
* It has been extensively rewritten by Theodore Ts'o to have a more
|
||||
* thread-safe interface.
|
||||
*/
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "hesiod.h"
|
||||
#include "hesiod_p.h"
|
||||
|
||||
/* Forward */
|
||||
|
||||
int hesiod_init(void **context);
|
||||
void hesiod_end(void *context);
|
||||
char * hesiod_to_bind(void *context, const char *name,
|
||||
const char *type);
|
||||
char ** hesiod_resolve(void *context, const char *name,
|
||||
const char *type);
|
||||
void hesiod_free_list(void *context, char **list);
|
||||
|
||||
static int parse_config_file(struct hesiod_p *ctx, const char *filename);
|
||||
static char ** get_txt_records(struct hesiod_p *ctx, int class,
|
||||
const char *name);
|
||||
static int init(struct hesiod_p *ctx);
|
||||
|
||||
/* Public */
|
||||
|
||||
/*
|
||||
* This function is called to initialize a hesiod_p.
|
||||
*/
|
||||
int
|
||||
hesiod_init(void **context) {
|
||||
struct hesiod_p *ctx;
|
||||
char *cp;
|
||||
|
||||
ctx = malloc(sizeof(struct hesiod_p));
|
||||
if (ctx == 0) {
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ctx->LHS = NULL;
|
||||
ctx->RHS = NULL;
|
||||
ctx->res = NULL;
|
||||
|
||||
if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) {
|
||||
#ifdef DEF_RHS
|
||||
/*
|
||||
* Use compiled in defaults.
|
||||
*/
|
||||
ctx->LHS = malloc(strlen(DEF_LHS) + 1);
|
||||
ctx->RHS = malloc(strlen(DEF_RHS) + 1);
|
||||
if (ctx->LHS == NULL || ctx->RHS == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
strcpy(ctx->LHS, DEF_LHS); /* (checked) */
|
||||
strcpy(ctx->RHS, DEF_RHS); /* (checked) */
|
||||
#else
|
||||
goto cleanup;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* The default RHS can be overridden by an environment
|
||||
* variable.
|
||||
*/
|
||||
if ((cp = getenv("HES_DOMAIN")) != NULL) {
|
||||
size_t RHSlen = strlen(cp) + 2;
|
||||
if (ctx->RHS)
|
||||
free(ctx->RHS);
|
||||
ctx->RHS = malloc(RHSlen);
|
||||
if (!ctx->RHS) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
if (cp[0] == '.') {
|
||||
strcpy(ctx->RHS, cp); /* (checked) */
|
||||
} else {
|
||||
strcpy(ctx->RHS, "."); /* (checked) */
|
||||
strcat(ctx->RHS, cp); /* (checked) */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no default hesiod realm set, we return an
|
||||
* error.
|
||||
*/
|
||||
if (!ctx->RHS) {
|
||||
errno = ENOEXEC;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (res_ninit(ctx->res) < 0)
|
||||
goto cleanup;
|
||||
#endif
|
||||
|
||||
*context = ctx;
|
||||
return (0);
|
||||
|
||||
cleanup:
|
||||
hesiod_end(ctx);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function deallocates the hesiod_p
|
||||
*/
|
||||
void
|
||||
hesiod_end(void *context) {
|
||||
struct hesiod_p *ctx = (struct hesiod_p *) context;
|
||||
int save_errno = errno;
|
||||
|
||||
if (ctx->res)
|
||||
res_nclose(ctx->res);
|
||||
if (ctx->RHS)
|
||||
free(ctx->RHS);
|
||||
if (ctx->LHS)
|
||||
free(ctx->LHS);
|
||||
if (ctx->res && ctx->free_res)
|
||||
(*ctx->free_res)(ctx->res);
|
||||
free(ctx);
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function takes a hesiod (name, type) and returns a DNS
|
||||
* name which is to be resolved.
|
||||
*/
|
||||
char *
|
||||
hesiod_to_bind(void *context, const char *name, const char *type) {
|
||||
struct hesiod_p *ctx = (struct hesiod_p *) context;
|
||||
char *bindname;
|
||||
char **rhs_list = NULL;
|
||||
const char *RHS, *cp;
|
||||
|
||||
/* Decide what our RHS is, and set cp to the end of the actual name. */
|
||||
if ((cp = strchr(name, '@')) != NULL) {
|
||||
if (strchr(cp + 1, '.'))
|
||||
RHS = cp + 1;
|
||||
else if ((rhs_list = hesiod_resolve(context, cp + 1,
|
||||
"rhs-extension")) != NULL)
|
||||
RHS = *rhs_list;
|
||||
else {
|
||||
errno = ENOENT;
|
||||
return (NULL);
|
||||
}
|
||||
} else {
|
||||
RHS = ctx->RHS;
|
||||
cp = name + strlen(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the space we need, including up to three periods and
|
||||
* the terminating NUL.
|
||||
*/
|
||||
if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) +
|
||||
(ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
if (rhs_list)
|
||||
hesiod_free_list(context, rhs_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now put together the DNS name. */
|
||||
memcpy(bindname, name, cp - name);
|
||||
bindname[cp - name] = '\0';
|
||||
strcat(bindname, ".");
|
||||
strcat(bindname, type);
|
||||
if (ctx->LHS) {
|
||||
if (ctx->LHS[0] != '.')
|
||||
strcat(bindname, ".");
|
||||
strcat(bindname, ctx->LHS);
|
||||
}
|
||||
if (RHS[0] != '.')
|
||||
strcat(bindname, ".");
|
||||
strcat(bindname, RHS);
|
||||
|
||||
if (rhs_list)
|
||||
hesiod_free_list(context, rhs_list);
|
||||
|
||||
return (bindname);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the core function. Given a hesiod (name, type), it
|
||||
* returns an array of strings returned by the resolver.
|
||||
*/
|
||||
char **
|
||||
hesiod_resolve(void *context, const char *name, const char *type) {
|
||||
struct hesiod_p *ctx = (struct hesiod_p *) context;
|
||||
char *bindname = hesiod_to_bind(context, name, type);
|
||||
char **retvec;
|
||||
|
||||
if (bindname == NULL)
|
||||
return (NULL);
|
||||
if (init(ctx) == -1) {
|
||||
free(bindname);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((retvec = get_txt_records(ctx, C_IN, bindname))) {
|
||||
free(bindname);
|
||||
return (retvec);
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
return (NULL);
|
||||
|
||||
retvec = get_txt_records(ctx, C_HS, bindname);
|
||||
free(bindname);
|
||||
return (retvec);
|
||||
}
|
||||
|
||||
void
|
||||
hesiod_free_list(void *context, char **list) {
|
||||
char **p;
|
||||
|
||||
UNUSED(context);
|
||||
|
||||
for (p = list; *p; p++)
|
||||
free(*p);
|
||||
free(list);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function parses the /etc/hesiod.conf file
|
||||
*/
|
||||
static int
|
||||
parse_config_file(struct hesiod_p *ctx, const char *filename) {
|
||||
char *key, *data, *cp, **cpp;
|
||||
char buf[MAXDNAME+7];
|
||||
FILE *fp;
|
||||
|
||||
/*
|
||||
* Clear the existing configuration variable, just in case
|
||||
* they're set.
|
||||
*/
|
||||
if (ctx->RHS)
|
||||
free(ctx->RHS);
|
||||
if (ctx->LHS)
|
||||
free(ctx->LHS);
|
||||
ctx->RHS = ctx->LHS = 0;
|
||||
|
||||
/*
|
||||
* Now open and parse the file...
|
||||
*/
|
||||
if (!(fp = fopen(filename, "r")))
|
||||
return (-1);
|
||||
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
cp = buf;
|
||||
if (*cp == '#' || *cp == '\n' || *cp == '\r')
|
||||
continue;
|
||||
while(*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
key = cp;
|
||||
while(*cp != ' ' && *cp != '\t' && *cp != '=')
|
||||
cp++;
|
||||
*cp++ = '\0';
|
||||
|
||||
while(*cp == ' ' || *cp == '\t' || *cp == '=')
|
||||
cp++;
|
||||
data = cp;
|
||||
while(*cp != ' ' && *cp != '\n' && *cp != '\r')
|
||||
cp++;
|
||||
*cp++ = '\0';
|
||||
|
||||
if (strcmp(key, "lhs") == 0)
|
||||
cpp = &ctx->LHS;
|
||||
else if (strcmp(key, "rhs") == 0)
|
||||
cpp = &ctx->RHS;
|
||||
else
|
||||
continue;
|
||||
|
||||
*cpp = malloc(strlen(data) + 1);
|
||||
if (!*cpp) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
strcpy(*cpp, data);
|
||||
}
|
||||
fclose(fp);
|
||||
return (0);
|
||||
|
||||
cleanup:
|
||||
fclose(fp);
|
||||
if (ctx->RHS)
|
||||
free(ctx->RHS);
|
||||
if (ctx->LHS)
|
||||
free(ctx->LHS);
|
||||
ctx->RHS = ctx->LHS = 0;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a DNS class and a DNS name, do a lookup for TXT records, and
|
||||
* return a list of them.
|
||||
*/
|
||||
static char **
|
||||
get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
|
||||
struct {
|
||||
int type; /* RR type */
|
||||
int class; /* RR class */
|
||||
int dlen; /* len of data section */
|
||||
u_char *data; /* pointer to data */
|
||||
} rr;
|
||||
HEADER *hp;
|
||||
u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP];
|
||||
u_char *cp, *erdata, *eom;
|
||||
char *dst, *edst, **list;
|
||||
int ancount, qdcount;
|
||||
int i, j, n, skip;
|
||||
|
||||
/*
|
||||
* Construct the query and send it.
|
||||
*/
|
||||
n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0,
|
||||
NULL, qbuf, MAX_HESRESP);
|
||||
if (n < 0) {
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP);
|
||||
if (n < 0) {
|
||||
errno = ECONNREFUSED;
|
||||
return (NULL);
|
||||
}
|
||||
if (n < HFIXEDSZ) {
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, parse the result.
|
||||
*/
|
||||
hp = (HEADER *) abuf;
|
||||
ancount = ntohs(hp->ancount);
|
||||
qdcount = ntohs(hp->qdcount);
|
||||
cp = abuf + sizeof(HEADER);
|
||||
eom = abuf + n;
|
||||
|
||||
/* Skip query, trying to get to the answer section which follows. */
|
||||
for (i = 0; i < qdcount; i++) {
|
||||
skip = dn_skipname(cp, eom);
|
||||
if (skip < 0 || cp + skip + QFIXEDSZ > eom) {
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
||||
cp += skip + QFIXEDSZ;
|
||||
}
|
||||
|
||||
list = malloc((ancount + 1) * sizeof(char *));
|
||||
if (!list) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
j = 0;
|
||||
for (i = 0; i < ancount; i++) {
|
||||
skip = dn_skipname(cp, eom);
|
||||
if (skip < 0) {
|
||||
errno = EMSGSIZE;
|
||||
goto cleanup;
|
||||
}
|
||||
cp += skip;
|
||||
if (cp + 3 * INT16SZ + INT32SZ > eom) {
|
||||
errno = EMSGSIZE;
|
||||
goto cleanup;
|
||||
}
|
||||
rr.type = ns_get16(cp);
|
||||
cp += INT16SZ;
|
||||
rr.class = ns_get16(cp);
|
||||
cp += INT16SZ + INT32SZ; /* skip the ttl, too */
|
||||
rr.dlen = ns_get16(cp);
|
||||
cp += INT16SZ;
|
||||
if (cp + rr.dlen > eom) {
|
||||
errno = EMSGSIZE;
|
||||
goto cleanup;
|
||||
}
|
||||
rr.data = cp;
|
||||
cp += rr.dlen;
|
||||
if (rr.class != class || rr.type != T_TXT)
|
||||
continue;
|
||||
if (!(list[j] = malloc(rr.dlen)))
|
||||
goto cleanup;
|
||||
dst = list[j++];
|
||||
edst = dst + rr.dlen;
|
||||
erdata = rr.data + rr.dlen;
|
||||
cp = rr.data;
|
||||
while (cp < erdata) {
|
||||
n = (unsigned char) *cp++;
|
||||
if (cp + n > eom || dst + n > edst) {
|
||||
errno = EMSGSIZE;
|
||||
goto cleanup;
|
||||
}
|
||||
memcpy(dst, cp, n);
|
||||
cp += n;
|
||||
dst += n;
|
||||
}
|
||||
if (cp != erdata) {
|
||||
errno = EMSGSIZE;
|
||||
goto cleanup;
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
list[j] = NULL;
|
||||
if (j == 0) {
|
||||
errno = ENOENT;
|
||||
goto cleanup;
|
||||
}
|
||||
return (list);
|
||||
|
||||
cleanup:
|
||||
for (i = 0; i < j; i++)
|
||||
free(list[i]);
|
||||
free(list);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct __res_state *
|
||||
__hesiod_res_get(void *context) {
|
||||
struct hesiod_p *ctx = context;
|
||||
|
||||
if (!ctx->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (res == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof *res);
|
||||
__hesiod_res_set(ctx, res, free);
|
||||
}
|
||||
|
||||
return (ctx->res);
|
||||
}
|
||||
|
||||
void
|
||||
__hesiod_res_set(void *context, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct hesiod_p *ctx = context;
|
||||
|
||||
if (ctx->res && ctx->free_res) {
|
||||
res_nclose(ctx->res);
|
||||
(*ctx->free_res)(ctx->res);
|
||||
}
|
||||
|
||||
ctx->res = res;
|
||||
ctx->free_res = free_res;
|
||||
}
|
||||
|
||||
static int
|
||||
init(struct hesiod_p *ctx) {
|
||||
|
||||
if (!ctx->res && !__hesiod_res_get(ctx))
|
||||
return (-1);
|
||||
|
||||
if (((ctx->res->options & RES_INIT) == 0U) &&
|
||||
(res_ninit(ctx->res) == -1))
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* hesiod_p.h -- private definitions for the hesiod library
|
||||
*/
|
||||
|
||||
#ifndef _HESIOD_P_H_INCLUDED
|
||||
#define _HESIOD_P_H_INCLUDED
|
||||
|
||||
#define DEF_RHS ".Athena.MIT.EDU" /* Defaults if HESIOD_CONF */
|
||||
#define DEF_LHS ".ns" /* file is not */
|
||||
/* present. */
|
||||
struct hesiod_p {
|
||||
char * LHS; /* normally ".ns" */
|
||||
char * RHS; /* AKA the default hesiod domain */
|
||||
struct __res_state * res; /* resolver context */
|
||||
void (*free_res)(void *);
|
||||
void (*res_set)(struct hesiod_p *, struct __res_state *,
|
||||
void (*)(void *));
|
||||
struct __res_state * (*res_get)(struct hesiod_p *);
|
||||
};
|
||||
|
||||
#define MAX_HESRESP 1024
|
||||
|
||||
#endif /*_HESIOD_P_H_INCLUDED*/
|
||||
@@ -1,592 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996, 1998 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <syslog.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <irp.h>
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "irp_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void irp_close(struct irs_acc *);
|
||||
|
||||
#define LINEINCR 128
|
||||
|
||||
#if !defined(SUN_LEN)
|
||||
#define SUN_LEN(su) \
|
||||
(sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path))
|
||||
#endif
|
||||
|
||||
|
||||
/* Public */
|
||||
|
||||
|
||||
/* send errors to syslog if true. */
|
||||
int irp_log_errors = 1;
|
||||
|
||||
/*
|
||||
* This module handles the irp module connection to irpd.
|
||||
*
|
||||
* The client expects a synchronous interface to functions like
|
||||
* getpwnam(3), so we can't use the ctl_* i/o library on this end of
|
||||
* the wire (it's used in the server).
|
||||
*/
|
||||
|
||||
/*
|
||||
* irs_acc *irs_irp_acc(const char *options);
|
||||
*
|
||||
* Initialize the irp module.
|
||||
*/
|
||||
struct irs_acc *
|
||||
irs_irp_acc(const char *options) {
|
||||
struct irs_acc *acc;
|
||||
struct irp_p *irp;
|
||||
|
||||
UNUSED(options);
|
||||
|
||||
if (!(acc = memget(sizeof *acc))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(acc, 0x5e, sizeof *acc);
|
||||
if (!(irp = memget(sizeof *irp))) {
|
||||
errno = ENOMEM;
|
||||
free(acc);
|
||||
return (NULL);
|
||||
}
|
||||
irp->inlast = 0;
|
||||
irp->incurr = 0;
|
||||
irp->fdCxn = -1;
|
||||
acc->private = irp;
|
||||
|
||||
#ifdef WANT_IRS_GR
|
||||
acc->gr_map = irs_irp_gr;
|
||||
#else
|
||||
acc->gr_map = NULL;
|
||||
#endif
|
||||
#ifdef WANT_IRS_PW
|
||||
acc->pw_map = irs_irp_pw;
|
||||
#else
|
||||
acc->pw_map = NULL;
|
||||
#endif
|
||||
acc->sv_map = irs_irp_sv;
|
||||
acc->pr_map = irs_irp_pr;
|
||||
acc->ho_map = irs_irp_ho;
|
||||
acc->nw_map = irs_irp_nw;
|
||||
acc->ng_map = irs_irp_ng;
|
||||
acc->close = irp_close;
|
||||
return (acc);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
irs_irp_connection_setup(struct irp_p *cxndata, int *warned) {
|
||||
if (irs_irp_is_connected(cxndata)) {
|
||||
return (0);
|
||||
} else if (irs_irp_connect(cxndata) != 0) {
|
||||
if (warned != NULL && !*warned) {
|
||||
syslog(LOG_ERR, "irpd connection failed: %m\n");
|
||||
(*warned)++;
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int irs_irp_connect(void);
|
||||
*
|
||||
* Sets up the connection to the remote irpd server.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, -1 on failure.
|
||||
*
|
||||
*/
|
||||
int
|
||||
irs_irp_connect(struct irp_p *pvt) {
|
||||
int flags;
|
||||
struct sockaddr *addr;
|
||||
struct sockaddr_in iaddr;
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
struct sockaddr_un uaddr;
|
||||
#endif
|
||||
long ipaddr;
|
||||
const char *irphost;
|
||||
int code;
|
||||
char text[256];
|
||||
int socklen = 0;
|
||||
|
||||
if (pvt->fdCxn != -1) {
|
||||
perror("fd != 1");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
memset(&uaddr, 0, sizeof uaddr);
|
||||
#endif
|
||||
memset(&iaddr, 0, sizeof iaddr);
|
||||
|
||||
irphost = getenv(IRPD_HOST_ENV);
|
||||
if (irphost == NULL) {
|
||||
irphost = "127.0.0.1";
|
||||
}
|
||||
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
if (irphost[0] == '/') {
|
||||
addr = (struct sockaddr *)&uaddr;
|
||||
strncpy(uaddr.sun_path, irphost, sizeof uaddr.sun_path);
|
||||
uaddr.sun_family = AF_UNIX;
|
||||
socklen = SUN_LEN(&uaddr);
|
||||
#ifdef HAVE_SA_LEN
|
||||
uaddr.sun_len = socklen;
|
||||
#endif
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (inet_pton(AF_INET, irphost, &ipaddr) != 1) {
|
||||
errno = EADDRNOTAVAIL;
|
||||
perror("inet_pton");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
addr = (struct sockaddr *)&iaddr;
|
||||
socklen = sizeof iaddr;
|
||||
#ifdef HAVE_SA_LEN
|
||||
iaddr.sin_len = socklen;
|
||||
#endif
|
||||
iaddr.sin_family = AF_INET;
|
||||
iaddr.sin_port = htons(IRPD_PORT);
|
||||
iaddr.sin_addr.s_addr = ipaddr;
|
||||
}
|
||||
|
||||
|
||||
pvt->fdCxn = socket(addr->sa_family, SOCK_STREAM, PF_UNSPEC);
|
||||
if (pvt->fdCxn < 0) {
|
||||
perror("socket");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (connect(pvt->fdCxn, addr, socklen) != 0) {
|
||||
perror("connect");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
flags = fcntl(pvt->fdCxn, F_GETFL, 0);
|
||||
if (flags < 0) {
|
||||
close(pvt->fdCxn);
|
||||
perror("close");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
flags |= O_NONBLOCK;
|
||||
if (fcntl(pvt->fdCxn, F_SETFL, flags) < 0) {
|
||||
close(pvt->fdCxn);
|
||||
perror("fcntl");
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
code = irs_irp_read_response(pvt, text, sizeof text);
|
||||
if (code != IRPD_WELCOME_CODE) {
|
||||
if (irp_log_errors) {
|
||||
syslog(LOG_WARNING, "Connection failed: %s", text);
|
||||
}
|
||||
irs_irp_disconnect(pvt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* int irs_irp_is_connected(struct irp_p *pvt);
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Non-zero if streams are setup to remote.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
irs_irp_is_connected(struct irp_p *pvt) {
|
||||
return (pvt->fdCxn >= 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void
|
||||
* irs_irp_disconnect(struct irp_p *pvt);
|
||||
*
|
||||
* Closes streams to remote.
|
||||
*/
|
||||
|
||||
void
|
||||
irs_irp_disconnect(struct irp_p *pvt) {
|
||||
if (pvt->fdCxn != -1) {
|
||||
close(pvt->fdCxn);
|
||||
pvt->fdCxn = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
irs_irp_read_line(struct irp_p *pvt, char *buffer, int len) {
|
||||
char *realstart = &pvt->inbuffer[0];
|
||||
char *p, *start, *end;
|
||||
int spare;
|
||||
int i;
|
||||
int buffpos = 0;
|
||||
int left = len - 1;
|
||||
|
||||
while (left > 0) {
|
||||
start = p = &pvt->inbuffer[pvt->incurr];
|
||||
end = &pvt->inbuffer[pvt->inlast];
|
||||
|
||||
while (p != end && *p != '\n')
|
||||
p++;
|
||||
|
||||
if (p == end) {
|
||||
/* Found no newline so shift data down if necessary
|
||||
* and append new data to buffer
|
||||
*/
|
||||
if (start > realstart) {
|
||||
memmove(realstart, start, end - start);
|
||||
pvt->inlast = end - start;
|
||||
start = realstart;
|
||||
pvt->incurr = 0;
|
||||
end = &pvt->inbuffer[pvt->inlast];
|
||||
}
|
||||
|
||||
spare = sizeof (pvt->inbuffer) - pvt->inlast;
|
||||
|
||||
p = end;
|
||||
i = read(pvt->fdCxn, end, spare);
|
||||
if (i < 0) {
|
||||
close(pvt->fdCxn);
|
||||
pvt->fdCxn = -1;
|
||||
return (buffpos > 0 ? buffpos : -1);
|
||||
} else if (i == 0) {
|
||||
return (buffpos);
|
||||
}
|
||||
|
||||
end += i;
|
||||
pvt->inlast += i;
|
||||
|
||||
while (p != end && *p != '\n')
|
||||
p++;
|
||||
}
|
||||
|
||||
if (p == end) {
|
||||
/* full buffer and still no newline */
|
||||
i = sizeof pvt->inbuffer;
|
||||
} else {
|
||||
/* include newline */
|
||||
i = p - start + 1;
|
||||
}
|
||||
|
||||
if (i > left)
|
||||
i = left;
|
||||
memcpy(buffer + buffpos, start, i);
|
||||
pvt->incurr += i;
|
||||
buffpos += i;
|
||||
buffer[buffpos] = '\0';
|
||||
|
||||
if (p != end) {
|
||||
left = 0;
|
||||
} else {
|
||||
left -= i;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "read line: %s\n", buffer);
|
||||
#endif
|
||||
return (buffpos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* int irp_read_response(struct irp_p *pvt);
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* The number found at the beginning of the line read from
|
||||
* FP. 0 on failure(0 is not a legal response code). The
|
||||
* rest of the line is discarded.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen) {
|
||||
char line[1024];
|
||||
int code;
|
||||
char *p;
|
||||
|
||||
if (irs_irp_read_line(pvt, line, sizeof line) <= 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
p = strchr(line, '\n');
|
||||
if (p == NULL) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (sscanf(line, "%d", &code) != 1) {
|
||||
code = 0;
|
||||
} else if (text != NULL && textlen > 0U) {
|
||||
p = line;
|
||||
while (isspace((unsigned char)*p)) p++;
|
||||
while (isdigit((unsigned char)*p)) p++;
|
||||
while (isspace((unsigned char)*p)) p++;
|
||||
strncpy(text, p, textlen - 1);
|
||||
p[textlen - 1] = '\0';
|
||||
}
|
||||
|
||||
return (code);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* char *irp_read_body(struct irp_p *pvt, size_t *size);
|
||||
*
|
||||
* Read in the body of a response. Terminated by a line with
|
||||
* just a dot on it. Lines should be terminated with a CR-LF
|
||||
* sequence, but we're nt piccky if the CR is missing.
|
||||
* No leading dot escaping is done as the protcol doesn't
|
||||
* use leading dots anywhere.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Pointer to null-terminated buffer allocated by memget.
|
||||
* *SIZE is set to the length of the buffer.
|
||||
*
|
||||
*/
|
||||
|
||||
char *
|
||||
irs_irp_read_body(struct irp_p *pvt, size_t *size) {
|
||||
char line[1024];
|
||||
u_int linelen;
|
||||
size_t len = LINEINCR;
|
||||
char *buffer = memget(len);
|
||||
int idx = 0;
|
||||
|
||||
for (;;) {
|
||||
if (irs_irp_read_line(pvt, line, sizeof line) <= 0 ||
|
||||
strchr(line, '\n') == NULL)
|
||||
goto death;
|
||||
|
||||
linelen = strlen(line);
|
||||
|
||||
if (line[linelen - 1] != '\n')
|
||||
goto death;
|
||||
|
||||
/* We're not strict about missing \r. Should we be?? */
|
||||
if (linelen > 2 && line[linelen - 2] == '\r') {
|
||||
line[linelen - 2] = '\n';
|
||||
line[linelen - 1] = '\0';
|
||||
linelen--;
|
||||
}
|
||||
|
||||
if (linelen == 2 && line[0] == '.') {
|
||||
*size = len;
|
||||
buffer[idx] = '\0';
|
||||
|
||||
return (buffer);
|
||||
}
|
||||
|
||||
if (linelen > (len - (idx + 1))) {
|
||||
char *p = memget(len + LINEINCR);
|
||||
|
||||
if (p == NULL)
|
||||
goto death;
|
||||
memcpy(p, buffer, len);
|
||||
memput(buffer, len);
|
||||
buffer = p;
|
||||
len += LINEINCR;
|
||||
}
|
||||
|
||||
memcpy(buffer + idx, line, linelen);
|
||||
idx += linelen;
|
||||
}
|
||||
death:
|
||||
memput(buffer, len);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int irs_irp_get_full_response(struct irp_p *pvt, int *code,
|
||||
* char **body, size_t *bodylen);
|
||||
*
|
||||
* Gets the response to a command. If the response indicates
|
||||
* there's a body to follow(code % 10 == 1), then the
|
||||
* body buffer is allcoated with memget and stored in
|
||||
* *BODY. The length of the allocated body buffer is stored
|
||||
* in *BODY. The caller must give the body buffer back to
|
||||
* memput when done. The results code is stored in *CODE.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 if a result was read. -1 on some sort of failure.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
irs_irp_get_full_response(struct irp_p *pvt, int *code, char *text,
|
||||
size_t textlen, char **body, size_t *bodylen) {
|
||||
int result = irs_irp_read_response(pvt, text, textlen);
|
||||
|
||||
*body = NULL;
|
||||
|
||||
if (result == 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
*code = result;
|
||||
|
||||
/* Code that matches 2xx is a good result code.
|
||||
* Code that matches xx1 means there's a response body coming.
|
||||
*/
|
||||
if ((result / 100) == 2 && (result % 10) == 1) {
|
||||
*body = irs_irp_read_body(pvt, bodylen);
|
||||
if (*body == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...);
|
||||
*
|
||||
* Sends command to remote connected via the PVT
|
||||
* struture. FMT and args after it are fprintf-like
|
||||
* arguments for formatting.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, -1 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buffer[1024];
|
||||
int pos = 0;
|
||||
int i, todo;
|
||||
|
||||
|
||||
if (pvt->fdCxn < 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
todo = vsprintf(buffer, fmt, ap);
|
||||
va_end(ap);
|
||||
if (todo > (int)sizeof(buffer) - 3) {
|
||||
syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()");
|
||||
exit(1);
|
||||
}
|
||||
strcat(buffer, "\r\n");
|
||||
todo = strlen(buffer);
|
||||
|
||||
while (todo > 0) {
|
||||
i = write(pvt->fdCxn, buffer + pos, todo);
|
||||
#if 0
|
||||
/* XXX brister */
|
||||
fprintf(stderr, "Wrote: \"");
|
||||
fwrite(buffer + pos, sizeof (char), todo, stderr);
|
||||
fprintf(stderr, "\"\n");
|
||||
#endif
|
||||
if (i < 0) {
|
||||
close(pvt->fdCxn);
|
||||
pvt->fdCxn = -1;
|
||||
return (-1);
|
||||
}
|
||||
todo -= i;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* Methods */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void irp_close(struct irs_acc *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
irp_close(struct irs_acc *this) {
|
||||
struct irp_p *irp = (struct irp_p *)this->private;
|
||||
|
||||
if (irp != NULL) {
|
||||
irs_irp_disconnect(irp);
|
||||
memput(irp, sizeof *irp);
|
||||
}
|
||||
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,429 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996,1998 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* Imports. */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <irp.h>
|
||||
#include <isc/irpmarshall.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "dns_p.h"
|
||||
#include "irp_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Definitions. */
|
||||
|
||||
#define MAXALIASES 35
|
||||
#define MAXADDRS 35
|
||||
#define Max(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
|
||||
struct pvt {
|
||||
struct irp_p *girpdata;
|
||||
int warned;
|
||||
struct hostent host;
|
||||
};
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void ho_close(struct irs_ho *this);
|
||||
static struct hostent * ho_byname(struct irs_ho *this, const char *name);
|
||||
static struct hostent * ho_byname2(struct irs_ho *this, const char *name,
|
||||
int af);
|
||||
static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
|
||||
int len, int af);
|
||||
static struct hostent * ho_next(struct irs_ho *this);
|
||||
static void ho_rewind(struct irs_ho *this);
|
||||
static void ho_minimize(struct irs_ho *this);
|
||||
|
||||
static void free_host(struct hostent *ho);
|
||||
static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name,
|
||||
const struct addrinfo *pai);
|
||||
|
||||
/* Public. */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct irs_ho * irs_irp_ho(struct irs_acc *this)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Initializes the irp_ho module.
|
||||
*
|
||||
*/
|
||||
|
||||
struct irs_ho *
|
||||
irs_irp_ho(struct irs_acc *this) {
|
||||
struct irs_ho *ho;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(ho = memget(sizeof *ho))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(ho, 0x0, sizeof *ho);
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
memput(ho, sizeof *ho);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pvt->girpdata = this->private;
|
||||
|
||||
ho->private = pvt;
|
||||
ho->close = ho_close;
|
||||
ho->byname = ho_byname;
|
||||
ho->byname2 = ho_byname2;
|
||||
ho->byaddr = ho_byaddr;
|
||||
ho->next = ho_next;
|
||||
ho->rewind = ho_rewind;
|
||||
ho->minimize = ho_minimize;
|
||||
ho->addrinfo = ho_addrinfo;
|
||||
|
||||
return (ho);
|
||||
}
|
||||
|
||||
/* Methods. */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void ho_close(struct irs_ho *this)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Closes down the module.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
ho_close(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
ho_minimize(this);
|
||||
|
||||
free_host(&pvt->host);
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct hostent * ho_byname(struct irs_ho *this, const char *name)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct hostent *
|
||||
ho_byname(struct irs_ho *this, const char *name) {
|
||||
return (ho_byname2(this, name, AF_INET));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct hostent * ho_byname2(struct irs_ho *this, const char *name, int af)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct hostent *
|
||||
ho_byname2(struct irs_ho *this, const char *name, int af) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct hostent *ho = &pvt->host;
|
||||
char *body = NULL;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
char text[256];
|
||||
|
||||
if (ho->h_name != NULL &&
|
||||
strcmp(name, ho->h_name) == 0 &&
|
||||
af == ho->h_addrtype) {
|
||||
return (ho);
|
||||
}
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "gethostbyname2 %s %s",
|
||||
name, ADDR_T_STR(af)) != 0)
|
||||
return (NULL);
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETHOST_OK) {
|
||||
free_host(ho);
|
||||
if (irp_unmarshall_ho(ho, body) != 0) {
|
||||
ho = NULL;
|
||||
}
|
||||
} else {
|
||||
ho = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (ho);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
|
||||
* int len, int af)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct hostent *
|
||||
ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct hostent *ho = &pvt->host;
|
||||
char *body = NULL;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
char **p;
|
||||
char paddr[MAXPADDRSIZE];
|
||||
char text[256];
|
||||
|
||||
if (ho->h_name != NULL &&
|
||||
af == ho->h_addrtype &&
|
||||
len == ho->h_length) {
|
||||
for (p = ho->h_addr_list ; *p != NULL ; p++) {
|
||||
if (memcmp(*p, addr, len) == 0)
|
||||
return (ho);
|
||||
}
|
||||
}
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (inet_ntop(af, addr, paddr, sizeof paddr) == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "gethostbyaddr %s %s",
|
||||
paddr, ADDR_T_STR(af)) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETHOST_OK) {
|
||||
free_host(ho);
|
||||
if (irp_unmarshall_ho(ho, body) != 0) {
|
||||
ho = NULL;
|
||||
}
|
||||
} else {
|
||||
ho = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (ho);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct hostent * ho_next(struct irs_ho *this)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* The implementation for gethostent(3). The first time it's
|
||||
* called all the data is pulled from the remote(i.e. what
|
||||
* the maximum number of gethostent(3) calls would return)
|
||||
* and that data is cached.
|
||||
*
|
||||
*/
|
||||
|
||||
static struct hostent *
|
||||
ho_next(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct hostent *ho = &pvt->host;
|
||||
char *body;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
char text[256];
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "gethostent") != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETHOST_OK) {
|
||||
free_host(ho);
|
||||
if (irp_unmarshall_ho(ho, body) != 0) {
|
||||
ho = NULL;
|
||||
}
|
||||
} else {
|
||||
ho = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (ho);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void ho_rewind(struct irs_ho *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
ho_rewind(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char text[256];
|
||||
int code;
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "sethostent") != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
|
||||
if (code != IRPD_GETHOST_SETOK) {
|
||||
if (irp_log_errors) {
|
||||
syslog(LOG_WARNING, "sethostent failed: %s", text);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void ho_minimize(struct irs_ho *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
ho_minimize(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
free_host(&pvt->host);
|
||||
|
||||
irs_irp_disconnect(pvt->girpdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void free_host(struct hostent *ho)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
free_host(struct hostent *ho) {
|
||||
char **p;
|
||||
|
||||
if (ho == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ho->h_name != NULL)
|
||||
free(ho->h_name);
|
||||
|
||||
if (ho->h_aliases != NULL) {
|
||||
for (p = ho->h_aliases ; *p != NULL ; p++)
|
||||
free(*p);
|
||||
free(ho->h_aliases);
|
||||
}
|
||||
|
||||
if (ho->h_addr_list != NULL) {
|
||||
for (p = ho->h_addr_list ; *p != NULL ; p++)
|
||||
free(*p);
|
||||
free(ho->h_addr_list);
|
||||
}
|
||||
}
|
||||
|
||||
/* dummy */
|
||||
static struct addrinfo *
|
||||
ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai)
|
||||
{
|
||||
UNUSED(this);
|
||||
UNUSED(name);
|
||||
UNUSED(pai);
|
||||
return(NULL);
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996, 1998 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <irp.h>
|
||||
#include <isc/memcluster.h>
|
||||
#include <isc/irpmarshall.h>
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "irp_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Definitions */
|
||||
|
||||
struct pvt {
|
||||
struct irp_p *girpdata;
|
||||
int warned;
|
||||
};
|
||||
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void ng_rewind(struct irs_ng *, const char*);
|
||||
static void ng_close(struct irs_ng *);
|
||||
static int ng_next(struct irs_ng *, const char **, const char **,
|
||||
const char **);
|
||||
static int ng_test(struct irs_ng *, const char *,
|
||||
const char *, const char *,
|
||||
const char *);
|
||||
static void ng_minimize(struct irs_ng *);
|
||||
|
||||
|
||||
/* Public */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct irs_ng * irs_irp_ng(struct irs_acc *this)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Intialize the irp netgroup module.
|
||||
*
|
||||
*/
|
||||
|
||||
struct irs_ng *
|
||||
irs_irp_ng(struct irs_acc *this) {
|
||||
struct irs_ng *ng;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(ng = memget(sizeof *ng))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(ng, 0x5e, sizeof *ng);
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
memput(ng, sizeof *ng);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pvt->girpdata = this->private;
|
||||
|
||||
ng->private = pvt;
|
||||
ng->close = ng_close;
|
||||
ng->next = ng_next;
|
||||
ng->test = ng_test;
|
||||
ng->rewind = ng_rewind;
|
||||
ng->minimize = ng_minimize;
|
||||
return (ng);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void ng_close(struct irs_ng *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
ng_close(struct irs_ng *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
ng_minimize(this);
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void ng_rewind(struct irs_ng *this, const char *group)
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
ng_rewind(struct irs_ng *this, const char *group) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char text[256];
|
||||
int code;
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata,
|
||||
"setnetgrent %s", group) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
|
||||
if (code != IRPD_GETNETGR_SETOK) {
|
||||
if (irp_log_errors) {
|
||||
syslog(LOG_WARNING, "setnetgrent(%s) failed: %s",
|
||||
group, text);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* int ng_next(struct irs_ng *this, const char **host, const char **user,
|
||||
* const char **domain)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Get the next netgroup item from the cache.
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
ng_next(struct irs_ng *this, const char **host, const char **user,
|
||||
const char **domain)
|
||||
{
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
int code;
|
||||
char *body = NULL;
|
||||
size_t bodylen;
|
||||
int rval = 0;
|
||||
char text[256];
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "getnetgrent") != 0)
|
||||
return (0);
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETNETGR_OK) {
|
||||
if (irp_unmarshall_ng(host, user, domain, body) == 0) {
|
||||
rval = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* int ng_test(struct irs_ng *this, const char *name, const char *host,
|
||||
* const char *user, const char *domain)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Search for a match in a netgroup.
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
ng_test(struct irs_ng *this, const char *name,
|
||||
const char *host, const char *user, const char *domain)
|
||||
{
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char *body = NULL;
|
||||
size_t bodylen = 0;
|
||||
int code;
|
||||
char text[256];
|
||||
int rval = 0;
|
||||
|
||||
UNUSED(name);
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (irp_marshall_ng(host, user, domain, &body, &bodylen) != 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "innetgr %s", body) == 0) {
|
||||
memput(body, bodylen);
|
||||
|
||||
code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
|
||||
if (code == IRPD_GETNETGR_MATCHES) {
|
||||
rval = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void ng_minimize(struct irs_ng *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
ng_minimize(struct irs_ng *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
irs_irp_disconnect(pvt->girpdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Private */
|
||||
|
||||
@@ -1,375 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996,1998 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#if 0
|
||||
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <irp.h>
|
||||
#include <isc/irpmarshall.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <isc/misc.h>
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "lcl_p.h"
|
||||
#include "irp_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#define MAXALIASES 35
|
||||
#define MAXADDRSIZE 4
|
||||
|
||||
struct pvt {
|
||||
struct irp_p *girpdata;
|
||||
int warned;
|
||||
struct nwent net;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void nw_close(struct irs_nw *);
|
||||
static struct nwent * nw_byname(struct irs_nw *, const char *, int);
|
||||
static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int);
|
||||
static struct nwent * nw_next(struct irs_nw *);
|
||||
static void nw_rewind(struct irs_nw *);
|
||||
static void nw_minimize(struct irs_nw *);
|
||||
|
||||
static void free_nw(struct nwent *nw);
|
||||
|
||||
|
||||
/* Public */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct irs_nw * irs_irp_nw(struct irs_acc *this)
|
||||
*
|
||||
*/
|
||||
|
||||
struct irs_nw *
|
||||
irs_irp_nw(struct irs_acc *this) {
|
||||
struct irs_nw *nw;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
|
||||
if (!(nw = memget(sizeof *nw))) {
|
||||
memput(pvt, sizeof *pvt);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(nw, 0x0, sizeof *nw);
|
||||
pvt->girpdata = this->private;
|
||||
|
||||
nw->private = pvt;
|
||||
nw->close = nw_close;
|
||||
nw->byname = nw_byname;
|
||||
nw->byaddr = nw_byaddr;
|
||||
nw->next = nw_next;
|
||||
nw->rewind = nw_rewind;
|
||||
nw->minimize = nw_minimize;
|
||||
return (nw);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void nw_close(struct irs_nw *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
nw_close(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
nw_minimize(this);
|
||||
|
||||
free_nw(&pvt->net);
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct nwent * nw_byaddr(struct irs_nw *this, void *net,
|
||||
* int length, int type)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct nwent *
|
||||
nw_byaddr(struct irs_nw *this, void *net, int length, int type) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct nwent *nw = &pvt->net;
|
||||
char *body = NULL;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
char paddr[24]; /* bigenough for ip4 w/ cidr spec. */
|
||||
char text[256];
|
||||
|
||||
if (inet_net_ntop(type, net, length, paddr, sizeof paddr) == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "getnetbyaddr %s %s",
|
||||
paddr, ADDR_T_STR(type)) != 0)
|
||||
return (NULL);
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETNET_OK) {
|
||||
free_nw(nw);
|
||||
if (irp_unmarshall_nw(nw, body) != 0) {
|
||||
nw = NULL;
|
||||
}
|
||||
} else {
|
||||
nw = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (nw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct nwent * nw_byname(struct irs_nw *this, const char *name, int type)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct nwent *
|
||||
nw_byname(struct irs_nw *this, const char *name, int type) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct nwent *nw = &pvt->net;
|
||||
char *body = NULL;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
char text[256];
|
||||
|
||||
if (nw->n_name != NULL &&
|
||||
strcmp(name, nw->n_name) == 0 &&
|
||||
nw->n_addrtype == type) {
|
||||
return (nw);
|
||||
}
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "getnetbyname %s", name) != 0)
|
||||
return (NULL);
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETNET_OK) {
|
||||
free_nw(nw);
|
||||
if (irp_unmarshall_nw(nw, body) != 0) {
|
||||
nw = NULL;
|
||||
}
|
||||
} else {
|
||||
nw = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (nw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void nw_rewind(struct irs_nw *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
nw_rewind(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char text[256];
|
||||
int code;
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "setnetent") != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
|
||||
if (code != IRPD_GETNET_SETOK) {
|
||||
if (irp_log_errors) {
|
||||
syslog(LOG_WARNING, "setnetent failed: %s", text);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct nwent * nw_next(struct irs_nw *this)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Prepares the cache if necessary and returns the first, or
|
||||
* next item from it.
|
||||
*/
|
||||
|
||||
static struct nwent *
|
||||
nw_next(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct nwent *nw = &pvt->net;
|
||||
char *body;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
char text[256];
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "getnetent") != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETNET_OK) {
|
||||
free_nw(nw);
|
||||
if (irp_unmarshall_nw(nw, body) != 0) {
|
||||
nw = NULL;
|
||||
}
|
||||
} else {
|
||||
nw = NULL;
|
||||
}
|
||||
|
||||
return (nw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void nw_minimize(struct irs_nw *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
nw_minimize(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
irs_irp_disconnect(pvt->girpdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* private. */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* static void free_passwd(struct passwd *pw);
|
||||
*
|
||||
* deallocate all the memory irp_unmarshall_pw allocated.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
free_nw(struct nwent *nw) {
|
||||
char **p;
|
||||
|
||||
if (nw == NULL)
|
||||
return;
|
||||
|
||||
if (nw->n_name != NULL)
|
||||
free(nw->n_name);
|
||||
|
||||
if (nw->n_aliases != NULL) {
|
||||
for (p = nw->n_aliases ; *p != NULL ; p++) {
|
||||
free(*p);
|
||||
}
|
||||
free(nw->n_aliases);
|
||||
}
|
||||
|
||||
if (nw->n_addr != NULL)
|
||||
free(nw->n_addr);
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _IRP_P_H_INCLUDED
|
||||
#define _IRP_P_H_INCLUDED
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct irp_p {
|
||||
char inbuffer[1024];
|
||||
int inlast; /* index of one past the last char in buffer */
|
||||
int incurr; /* index of the next char to be read from buffer */
|
||||
|
||||
int fdCxn;
|
||||
};
|
||||
|
||||
/*
|
||||
* Externs.
|
||||
*/
|
||||
|
||||
extern struct irs_acc * irs_irp_acc __P((const char *));
|
||||
extern struct irs_gr * irs_irp_gr __P((struct irs_acc *));
|
||||
extern struct irs_pw * irs_irp_pw __P((struct irs_acc *));
|
||||
extern struct irs_sv * irs_irp_sv __P((struct irs_acc *));
|
||||
extern struct irs_pr * irs_irp_pr __P((struct irs_acc *));
|
||||
extern struct irs_ho * irs_irp_ho __P((struct irs_acc *));
|
||||
extern struct irs_nw * irs_irp_nw __P((struct irs_acc *));
|
||||
extern struct irs_ng * irs_irp_ng __P((struct irs_acc *));
|
||||
|
||||
int irs_irp_connect(struct irp_p *pvt);
|
||||
int irs_irp_is_connected(struct irp_p *pvt);
|
||||
void irs_irp_disconnect(struct irp_p *pvt);
|
||||
int irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen);
|
||||
char *irs_irp_read_body(struct irp_p *pvt, size_t *size);
|
||||
int irs_irp_get_full_response(struct irp_p *pvt, int *code,
|
||||
char *text, size_t textlen,
|
||||
char **body, size_t *bodylen);
|
||||
|
||||
extern int irp_log_errors;
|
||||
|
||||
#endif
|
||||
@@ -1,353 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* extern */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <netdb.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <irp.h>
|
||||
#include <isc/memcluster.h>
|
||||
#include <isc/irpmarshall.h>
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "lcl_p.h"
|
||||
#include "irp_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
|
||||
#define MAXALIASES 35
|
||||
|
||||
/* Types */
|
||||
|
||||
struct pvt {
|
||||
struct irp_p *girpdata;
|
||||
int warned;
|
||||
struct protoent proto;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void pr_close(struct irs_pr *);
|
||||
static struct protoent * pr_next(struct irs_pr *);
|
||||
static struct protoent * pr_byname(struct irs_pr *, const char *);
|
||||
static struct protoent * pr_bynumber(struct irs_pr *, int);
|
||||
static void pr_rewind(struct irs_pr *);
|
||||
static void pr_minimize(struct irs_pr *);
|
||||
|
||||
static void free_proto(struct protoent *pr);
|
||||
|
||||
/* Public */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct irs_pr * irs_irp_pr(struct irs_acc *this)
|
||||
*
|
||||
*/
|
||||
|
||||
struct irs_pr *
|
||||
irs_irp_pr(struct irs_acc *this) {
|
||||
struct irs_pr *pr;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(pr = memget(sizeof *pr))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pr, 0x0, sizeof *pr);
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
memput(pr, sizeof *pr);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pvt->girpdata = this->private;
|
||||
|
||||
pr->private = pvt;
|
||||
pr->close = pr_close;
|
||||
pr->byname = pr_byname;
|
||||
pr->bynumber = pr_bynumber;
|
||||
pr->next = pr_next;
|
||||
pr->rewind = pr_rewind;
|
||||
pr->minimize = pr_minimize;
|
||||
return (pr);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void pr_close(struct irs_pr *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
pr_close(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
pr_minimize(this);
|
||||
|
||||
free_proto(&pvt->proto);
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct protoent * pr_byname(struct irs_pr *this, const char *name)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct protoent *
|
||||
pr_byname(struct irs_pr *this, const char *name) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct protoent *pr = &pvt->proto;
|
||||
char *body = NULL;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
int i;
|
||||
char text[256];
|
||||
|
||||
if (pr->p_name != NULL && strcmp(name, pr->p_name) == 0) {
|
||||
return (pr);
|
||||
}
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
i = irs_irp_send_command(pvt->girpdata, "getprotobyname %s", name);
|
||||
if (i != 0)
|
||||
return (NULL);
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETPROTO_OK) {
|
||||
free_proto(pr);
|
||||
if (irp_unmarshall_pr(pr, body) != 0) {
|
||||
pr = NULL;
|
||||
}
|
||||
} else {
|
||||
pr = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (pr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct protoent * pr_bynumber(struct irs_pr *this, int proto)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct protoent *
|
||||
pr_bynumber(struct irs_pr *this, int proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct protoent *pr = &pvt->proto;
|
||||
char *body = NULL;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
int i;
|
||||
char text[256];
|
||||
|
||||
if (pr->p_name != NULL && proto == pr->p_proto) {
|
||||
return (pr);
|
||||
}
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
i = irs_irp_send_command(pvt->girpdata, "getprotobynumber %d", proto);
|
||||
if (i != 0)
|
||||
return (NULL);
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETPROTO_OK) {
|
||||
free_proto(pr);
|
||||
if (irp_unmarshall_pr(pr, body) != 0) {
|
||||
pr = NULL;
|
||||
}
|
||||
} else {
|
||||
pr = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (pr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void pr_rewind(struct irs_pr *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
pr_rewind(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char text[256];
|
||||
int code;
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "setprotoent") != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
|
||||
if (code != IRPD_GETPROTO_SETOK) {
|
||||
if (irp_log_errors) {
|
||||
syslog(LOG_WARNING, "setprotoent failed: %s", text);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct protoent * pr_next(struct irs_pr *this)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Prepares the cache if necessary and returns the next item in it.
|
||||
*
|
||||
*/
|
||||
|
||||
static struct protoent *
|
||||
pr_next(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct protoent *pr = &pvt->proto;
|
||||
char *body;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
char text[256];
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "getprotoent") != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETPROTO_OK) {
|
||||
free_proto(pr);
|
||||
if (irp_unmarshall_pr(pr, body) != 0) {
|
||||
pr = NULL;
|
||||
}
|
||||
} else {
|
||||
pr = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (pr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void pr_minimize(struct irs_pr *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
pr_minimize(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
irs_irp_disconnect(pvt->girpdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* static void free_proto(struct protoent *pw);
|
||||
*
|
||||
* Deallocate all the memory irp_unmarshall_pr allocated.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
free_proto(struct protoent *pr) {
|
||||
char **p;
|
||||
|
||||
if (pr == NULL)
|
||||
return;
|
||||
|
||||
if (pr->p_name != NULL)
|
||||
free(pr->p_name);
|
||||
|
||||
for (p = pr->p_aliases ; p != NULL && *p != NULL ; p++)
|
||||
free(*p);
|
||||
}
|
||||
@@ -1,369 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996,1998 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* extern */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
#include <db.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <irp.h>
|
||||
#include <isc/irpmarshall.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "lcl_p.h"
|
||||
#include "irp_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Types */
|
||||
|
||||
struct pvt {
|
||||
struct irp_p *girpdata;
|
||||
int warned;
|
||||
struct servent service;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void sv_close(struct irs_sv*);
|
||||
static struct servent * sv_next(struct irs_sv *);
|
||||
static struct servent * sv_byname(struct irs_sv *, const char *,
|
||||
const char *);
|
||||
static struct servent * sv_byport(struct irs_sv *, int, const char *);
|
||||
static void sv_rewind(struct irs_sv *);
|
||||
static void sv_minimize(struct irs_sv *);
|
||||
|
||||
static void free_service(struct servent *sv);
|
||||
|
||||
|
||||
|
||||
/* Public */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct irs_sv * irs_irp_sv(struct irs_acc *this)
|
||||
*
|
||||
*/
|
||||
|
||||
struct irs_sv *
|
||||
irs_irp_sv(struct irs_acc *this) {
|
||||
struct irs_sv *sv;
|
||||
struct pvt *pvt;
|
||||
|
||||
if ((sv = memget(sizeof *sv)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(sv, 0x0, sizeof *sv);
|
||||
|
||||
if ((pvt = memget(sizeof *pvt)) == NULL) {
|
||||
memput(sv, sizeof *sv);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pvt->girpdata = this->private;
|
||||
|
||||
sv->private = pvt;
|
||||
sv->close = sv_close;
|
||||
sv->next = sv_next;
|
||||
sv->byname = sv_byname;
|
||||
sv->byport = sv_byport;
|
||||
sv->rewind = sv_rewind;
|
||||
sv->minimize = sv_minimize;
|
||||
|
||||
return (sv);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void sv_close(struct irs_sv *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
sv_close(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
sv_minimize(this);
|
||||
|
||||
free_service(&pvt->service);
|
||||
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct servent * sv_next(struct irs_sv *this)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Fills the cache if necessary and returns the next item from it.
|
||||
*
|
||||
*/
|
||||
|
||||
static struct servent *
|
||||
sv_next(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct servent *sv = &pvt->service;
|
||||
char *body;
|
||||
size_t bodylen;
|
||||
int code;
|
||||
char text[256];
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETSERVICE_OK) {
|
||||
free_service(sv);
|
||||
if (irp_unmarshall_sv(sv, body) != 0) {
|
||||
sv = NULL;
|
||||
}
|
||||
} else {
|
||||
sv = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (sv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct servent * sv_byname(struct irs_sv *this, const char *name,
|
||||
* const char *proto)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct servent *
|
||||
sv_byname(struct irs_sv *this, const char *name, const char *proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct servent *sv = &pvt->service;
|
||||
char *body;
|
||||
char text[256];
|
||||
size_t bodylen;
|
||||
int code;
|
||||
|
||||
if (sv->s_name != NULL &&
|
||||
strcmp(name, sv->s_name) == 0 &&
|
||||
strcasecmp(proto, sv->s_proto) == 0) {
|
||||
return (sv);
|
||||
}
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s",
|
||||
name, proto) != 0)
|
||||
return (NULL);
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETSERVICE_OK) {
|
||||
free_service(sv);
|
||||
if (irp_unmarshall_sv(sv, body) != 0) {
|
||||
sv = NULL;
|
||||
}
|
||||
} else {
|
||||
sv = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (sv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* struct servent * sv_byport(struct irs_sv *this, int port,
|
||||
* const char *proto)
|
||||
*
|
||||
*/
|
||||
|
||||
static struct servent *
|
||||
sv_byport(struct irs_sv *this, int port, const char *proto) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct servent *sv = &pvt->service;
|
||||
char *body;
|
||||
size_t bodylen;
|
||||
char text[256];
|
||||
int code;
|
||||
|
||||
if (sv->s_name != NULL &&
|
||||
port == sv->s_port &&
|
||||
strcasecmp(proto, sv->s_proto) == 0) {
|
||||
return (sv);
|
||||
}
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s",
|
||||
ntohs((short)port), proto) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (irs_irp_get_full_response(pvt->girpdata, &code,
|
||||
text, sizeof text,
|
||||
&body, &bodylen) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (code == IRPD_GETSERVICE_OK) {
|
||||
free_service(sv);
|
||||
if (irp_unmarshall_sv(sv, body) != 0) {
|
||||
sv = NULL;
|
||||
}
|
||||
} else {
|
||||
sv = NULL;
|
||||
}
|
||||
|
||||
if (body != NULL) {
|
||||
memput(body, bodylen);
|
||||
}
|
||||
|
||||
return (sv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void sv_rewind(struct irs_sv *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
sv_rewind(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char text[256];
|
||||
int code;
|
||||
|
||||
if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
|
||||
if (code != IRPD_GETSERVICE_SETOK) {
|
||||
if (irp_log_errors) {
|
||||
syslog(LOG_WARNING, "setservent failed: %s", text);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* void sv_minimize(struct irs_sv *this)
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
sv_minimize(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
irs_irp_disconnect(pvt->girpdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
free_service(struct servent *sv) {
|
||||
char **p;
|
||||
|
||||
if (sv == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sv->s_name != NULL) {
|
||||
free(sv->s_name);
|
||||
}
|
||||
|
||||
for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) {
|
||||
free(*p);
|
||||
}
|
||||
|
||||
if (sv->s_proto != NULL) {
|
||||
free(sv->s_proto);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#ifndef __BIND_NOSTATIC
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#ifdef DO_PTHREADS
|
||||
#include <TLS.h>
|
||||
#endif
|
||||
|
||||
#include <irs.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_data.h"
|
||||
#undef _res
|
||||
#if !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
|
||||
#undef h_errno
|
||||
extern int h_errno;
|
||||
#endif
|
||||
|
||||
extern struct __res_state _res;
|
||||
|
||||
#ifdef DO_PTHREADS
|
||||
int32 gIRSInitKey;
|
||||
#else
|
||||
static struct net_data *net_data;
|
||||
#endif
|
||||
|
||||
void
|
||||
irs_destroy(void) {
|
||||
#ifndef DO_PTHREADS
|
||||
if (net_data != NULL)
|
||||
net_data_destroy(net_data);
|
||||
net_data = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
net_data_destroy(void *p) {
|
||||
struct net_data *net_data = p;
|
||||
|
||||
res_ndestroy(net_data->res);
|
||||
if (net_data->gr != NULL) {
|
||||
(*net_data->gr->close)(net_data->gr);
|
||||
net_data->gr = NULL;
|
||||
}
|
||||
if (net_data->pw != NULL) {
|
||||
(*net_data->pw->close)(net_data->pw);
|
||||
net_data->pw = NULL;
|
||||
}
|
||||
if (net_data->sv != NULL) {
|
||||
(*net_data->sv->close)(net_data->sv);
|
||||
net_data->sv = NULL;
|
||||
}
|
||||
if (net_data->pr != NULL) {
|
||||
(*net_data->pr->close)(net_data->pr);
|
||||
net_data->pr = NULL;
|
||||
}
|
||||
if (net_data->ho != NULL) {
|
||||
(*net_data->ho->close)(net_data->ho);
|
||||
net_data->ho = NULL;
|
||||
}
|
||||
if (net_data->nw != NULL) {
|
||||
(*net_data->nw->close)(net_data->nw);
|
||||
net_data->nw = NULL;
|
||||
}
|
||||
if (net_data->ng != NULL) {
|
||||
(*net_data->ng->close)(net_data->ng);
|
||||
net_data->ng = NULL;
|
||||
}
|
||||
if (net_data->ho_data != NULL) {
|
||||
free(net_data->ho_data);
|
||||
net_data->ho_data = NULL;
|
||||
}
|
||||
if (net_data->nw_data != NULL) {
|
||||
free(net_data->nw_data);
|
||||
net_data->nw_data = NULL;
|
||||
}
|
||||
|
||||
(*net_data->irs->close)(net_data->irs);
|
||||
memput(net_data, sizeof *net_data);
|
||||
}
|
||||
|
||||
/* applications that need a specific config file other than
|
||||
* _PATH_IRS_CONF should call net_data_init directly rather than letting
|
||||
* the various wrapper functions make the first call. - brister
|
||||
*/
|
||||
|
||||
struct net_data *
|
||||
net_data_init(const char *conf_file) {
|
||||
#ifdef DO_PTHREADS
|
||||
#ifndef LIBBIND_MUTEX_INITIALIZER
|
||||
#define LIBBIND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
#endif
|
||||
struct net_data *net_data;
|
||||
|
||||
net_data = tls_get(gIRSInitKey);
|
||||
#endif
|
||||
|
||||
if (net_data == NULL) {
|
||||
net_data = net_data_create(conf_file);
|
||||
if (net_data == NULL)
|
||||
return (NULL);
|
||||
#ifdef DO_PTHREADS
|
||||
on_exit_thread(net_data_destroy, net_data);
|
||||
tls_set(gIRSInitKey, net_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
return (net_data);
|
||||
}
|
||||
|
||||
struct net_data *
|
||||
net_data_create(const char *conf_file) {
|
||||
struct net_data *net_data;
|
||||
|
||||
net_data = memget(sizeof (struct net_data));
|
||||
if (net_data == NULL)
|
||||
return (NULL);
|
||||
memset(net_data, 0, sizeof (struct net_data));
|
||||
|
||||
if ((net_data->irs = irs_gen_acc("", conf_file)) == NULL) {
|
||||
memput(net_data, sizeof (struct net_data));
|
||||
return (NULL);
|
||||
}
|
||||
#ifndef DO_PTHREADS
|
||||
(*net_data->irs->res_set)(net_data->irs, &_res, NULL);
|
||||
#endif
|
||||
|
||||
net_data->res = (*net_data->irs->res_get)(net_data->irs);
|
||||
if (net_data->res == NULL) {
|
||||
(*net_data->irs->close)(net_data->irs);
|
||||
memput(net_data, sizeof (struct net_data));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((net_data->res->options & RES_INIT) == 0U &&
|
||||
res_ninit(net_data->res) == -1) {
|
||||
(*net_data->irs->close)(net_data->irs);
|
||||
memput(net_data, sizeof (struct net_data));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (net_data);
|
||||
}
|
||||
|
||||
void
|
||||
net_data_minimize(struct net_data *net_data) {
|
||||
res_nclose(net_data->res);
|
||||
}
|
||||
|
||||
#ifdef _REENTRANT
|
||||
struct __res_state *
|
||||
__res_state(void) {
|
||||
/* NULL param here means use the default config file. */
|
||||
struct net_data *net_data = net_data_init(NULL);
|
||||
if (net_data && net_data->res)
|
||||
return (net_data->res);
|
||||
|
||||
return (&_res);
|
||||
}
|
||||
#else
|
||||
#ifdef __linux
|
||||
struct __res_state *
|
||||
__res_state(void) {
|
||||
return (&_res);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int *
|
||||
__h_errno(void) {
|
||||
/* NULL param here means use the default config file. */
|
||||
struct net_data *net_data = net_data_init(NULL);
|
||||
if (net_data && net_data->res)
|
||||
return (&net_data->res->res_h_errno);
|
||||
#if !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
|
||||
return(&_res.res_h_errno);
|
||||
#else
|
||||
return (&h_errno);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
__h_errno_set(struct __res_state *res, int err) {
|
||||
|
||||
|
||||
#if (__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
|
||||
res->res_h_errno = err;
|
||||
#else
|
||||
h_errno = res->res_h_errno = err;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*__BIND_NOSTATIC*/
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __BIND_NOSTATIC
|
||||
|
||||
#define net_data_init __net_data_init
|
||||
|
||||
struct net_data {
|
||||
struct irs_acc * irs;
|
||||
|
||||
struct irs_gr * gr;
|
||||
struct irs_pw * pw;
|
||||
struct irs_sv * sv;
|
||||
struct irs_pr * pr;
|
||||
struct irs_ho * ho;
|
||||
struct irs_nw * nw;
|
||||
struct irs_ng * ng;
|
||||
|
||||
struct group * gr_last;
|
||||
struct passwd * pw_last;
|
||||
struct servent * sv_last;
|
||||
struct protoent * pr_last;
|
||||
struct netent * nw_last; /* should have been ne_last */
|
||||
struct nwent * nww_last;
|
||||
struct hostent * ho_last;
|
||||
|
||||
unsigned int gr_stayopen :1;
|
||||
unsigned int pw_stayopen :1;
|
||||
unsigned int sv_stayopen :1;
|
||||
unsigned int pr_stayopen :1;
|
||||
unsigned int ho_stayopen :1;
|
||||
unsigned int nw_stayopen :1;
|
||||
|
||||
void * nw_data;
|
||||
void * ho_data;
|
||||
|
||||
struct __res_state * res; /* for gethostent.c */
|
||||
|
||||
};
|
||||
|
||||
extern struct net_data * net_data_init(const char *conf_file);
|
||||
extern void net_data_minimize(struct net_data *);
|
||||
|
||||
#endif /*__BIND_NOSTATIC*/
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _IRS_P_H_INCLUDED
|
||||
#define _IRS_P_H_INCLUDED
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
#define IRS_SV_MAXALIASES 35
|
||||
|
||||
struct lcl_sv {
|
||||
FILE * fp;
|
||||
char line[BUFSIZ+1];
|
||||
struct servent serv;
|
||||
char * serv_aliases[IRS_SV_MAXALIASES];
|
||||
};
|
||||
|
||||
#define irs_nul_ng __irs_nul_ng
|
||||
#define map_v4v6_address __map_v4v6_address
|
||||
#define make_group_list __make_group_list
|
||||
#define irs_lclsv_fnxt __irs_lclsv_fnxt
|
||||
|
||||
extern void map_v4v6_address(const char *src, char *dst);
|
||||
extern int make_group_list(struct irs_gr *, const char *,
|
||||
gid_t, gid_t *, int *);
|
||||
extern struct irs_ng * irs_nul_ng(struct irs_acc *);
|
||||
extern struct servent * irs_lclsv_fnxt(struct lcl_sv *);
|
||||
|
||||
#endif
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "lcl_p.h"
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void lcl_close(struct irs_acc *);
|
||||
static struct __res_state * lcl_res_get(struct irs_acc *);
|
||||
static void lcl_res_set(struct irs_acc *, struct __res_state *,
|
||||
void (*)(void *));
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_acc *
|
||||
irs_lcl_acc(const char *options) {
|
||||
struct irs_acc *acc;
|
||||
struct lcl_p *lcl;
|
||||
|
||||
UNUSED(options);
|
||||
|
||||
if (!(acc = memget(sizeof *acc))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(acc, 0x5e, sizeof *acc);
|
||||
if (!(lcl = memget(sizeof *lcl))) {
|
||||
errno = ENOMEM;
|
||||
free(acc);
|
||||
return (NULL);
|
||||
}
|
||||
memset(lcl, 0x5e, sizeof *lcl);
|
||||
lcl->res = NULL;
|
||||
lcl->free_res = NULL;
|
||||
acc->private = lcl;
|
||||
#ifdef WANT_IRS_GR
|
||||
acc->gr_map = irs_lcl_gr;
|
||||
#else
|
||||
acc->gr_map = NULL;
|
||||
#endif
|
||||
#ifdef WANT_IRS_PW
|
||||
acc->pw_map = irs_lcl_pw;
|
||||
#else
|
||||
acc->pw_map = NULL;
|
||||
#endif
|
||||
acc->sv_map = irs_lcl_sv;
|
||||
acc->pr_map = irs_lcl_pr;
|
||||
acc->ho_map = irs_lcl_ho;
|
||||
acc->nw_map = irs_lcl_nw;
|
||||
acc->ng_map = irs_lcl_ng;
|
||||
acc->res_get = lcl_res_get;
|
||||
acc->res_set = lcl_res_set;
|
||||
acc->close = lcl_close;
|
||||
return (acc);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
static struct __res_state *
|
||||
lcl_res_get(struct irs_acc *this) {
|
||||
struct lcl_p *lcl = (struct lcl_p *)this->private;
|
||||
|
||||
if (lcl->res == NULL) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
memset(res, 0, sizeof *res);
|
||||
lcl_res_set(this, res, free);
|
||||
}
|
||||
|
||||
if ((lcl->res->options & RES_INIT) == 0U &&
|
||||
res_ninit(lcl->res) < 0)
|
||||
return (NULL);
|
||||
|
||||
return (lcl->res);
|
||||
}
|
||||
|
||||
static void
|
||||
lcl_res_set(struct irs_acc *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct lcl_p *lcl = (struct lcl_p *)this->private;
|
||||
|
||||
if (lcl->res && lcl->free_res) {
|
||||
res_nclose(lcl->res);
|
||||
(*lcl->free_res)(lcl->res);
|
||||
}
|
||||
|
||||
lcl->res = res;
|
||||
lcl->free_res = free_res;
|
||||
}
|
||||
|
||||
static void
|
||||
lcl_close(struct irs_acc *this) {
|
||||
struct lcl_p *lcl = (struct lcl_p *)this->private;
|
||||
|
||||
if (lcl) {
|
||||
if (lcl->free_res)
|
||||
(*lcl->free_res)(lcl->res);
|
||||
memput(lcl, sizeof *lcl);
|
||||
}
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
@@ -1,576 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1985, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */
|
||||
/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* Imports. */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "dns_p.h"
|
||||
#include "lcl_p.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) sprintf x
|
||||
#endif
|
||||
|
||||
/* Definitions. */
|
||||
|
||||
#define MAXALIASES 35
|
||||
#define MAXADDRS 35
|
||||
#define Max(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#if PACKETSZ > 1024
|
||||
#define MAXPACKET PACKETSZ
|
||||
#else
|
||||
#define MAXPACKET 1024
|
||||
#endif
|
||||
|
||||
struct pvt {
|
||||
FILE * fp;
|
||||
struct hostent host;
|
||||
char * h_addr_ptrs[MAXADDRS + 1];
|
||||
char * host_aliases[MAXALIASES];
|
||||
char hostbuf[8*1024];
|
||||
u_char host_addr[16]; /* IPv4 or IPv6 */
|
||||
struct __res_state *res;
|
||||
void (*free_res)(void *);
|
||||
};
|
||||
|
||||
typedef union {
|
||||
int32_t al;
|
||||
char ac;
|
||||
} align;
|
||||
|
||||
static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
|
||||
static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void ho_close(struct irs_ho *this);
|
||||
static struct hostent * ho_byname(struct irs_ho *this, const char *name);
|
||||
static struct hostent * ho_byname2(struct irs_ho *this, const char *name,
|
||||
int af);
|
||||
static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
|
||||
int len, int af);
|
||||
static struct hostent * ho_next(struct irs_ho *this);
|
||||
static void ho_rewind(struct irs_ho *this);
|
||||
static void ho_minimize(struct irs_ho *this);
|
||||
static struct __res_state * ho_res_get(struct irs_ho *this);
|
||||
static void ho_res_set(struct irs_ho *this,
|
||||
struct __res_state *res,
|
||||
void (*free_res)(void *));
|
||||
static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name,
|
||||
const struct addrinfo *pai);
|
||||
|
||||
static size_t ns_namelen(const char *);
|
||||
static int init(struct irs_ho *this);
|
||||
|
||||
/* Portability. */
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
/* Public. */
|
||||
|
||||
struct irs_ho *
|
||||
irs_lcl_ho(struct irs_acc *this) {
|
||||
struct irs_ho *ho;
|
||||
struct pvt *pvt;
|
||||
|
||||
UNUSED(this);
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
if (!(ho = memget(sizeof *ho))) {
|
||||
memput(pvt, sizeof *pvt);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(ho, 0x5e, sizeof *ho);
|
||||
ho->private = pvt;
|
||||
ho->close = ho_close;
|
||||
ho->byname = ho_byname;
|
||||
ho->byname2 = ho_byname2;
|
||||
ho->byaddr = ho_byaddr;
|
||||
ho->next = ho_next;
|
||||
ho->rewind = ho_rewind;
|
||||
ho->minimize = ho_minimize;
|
||||
ho->res_get = ho_res_get;
|
||||
ho->res_set = ho_res_set;
|
||||
ho->addrinfo = ho_addrinfo;
|
||||
return (ho);
|
||||
}
|
||||
|
||||
/* Methods. */
|
||||
|
||||
static void
|
||||
ho_close(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
ho_minimize(this);
|
||||
if (pvt->fp)
|
||||
(void) fclose(pvt->fp);
|
||||
if (pvt->res && pvt->free_res)
|
||||
(*pvt->free_res)(pvt->res);
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct hostent *
|
||||
ho_byname(struct irs_ho *this, const char *name) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct hostent *hp;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
if (pvt->res->options & RES_USE_INET6) {
|
||||
hp = ho_byname2(this, name, AF_INET6);
|
||||
if (hp)
|
||||
return (hp);
|
||||
}
|
||||
return (ho_byname2(this, name, AF_INET));
|
||||
}
|
||||
|
||||
static struct hostent *
|
||||
ho_byname2(struct irs_ho *this, const char *name, int af) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct hostent *hp;
|
||||
char **hap;
|
||||
size_t n;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
ho_rewind(this);
|
||||
n = ns_namelen(name);
|
||||
while ((hp = ho_next(this)) != NULL) {
|
||||
size_t nn;
|
||||
|
||||
if (hp->h_addrtype != af)
|
||||
continue;
|
||||
nn = ns_namelen(hp->h_name);
|
||||
if (strncasecmp(hp->h_name, name, Max(n, nn)) == 0)
|
||||
goto found;
|
||||
for (hap = hp->h_aliases; *hap; hap++) {
|
||||
nn = ns_namelen(*hap);
|
||||
if (strncasecmp(*hap, name, Max(n, nn)) == 0)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found:
|
||||
if (!hp) {
|
||||
RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
|
||||
return (NULL);
|
||||
}
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
|
||||
return (hp);
|
||||
}
|
||||
|
||||
static struct hostent *
|
||||
ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
const u_char *uaddr = addr;
|
||||
struct hostent *hp;
|
||||
int size;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
if (af == AF_INET6 && len == IN6ADDRSZ &&
|
||||
(!memcmp(uaddr, mapped, sizeof mapped) ||
|
||||
!memcmp(uaddr, tunnelled, sizeof tunnelled))) {
|
||||
/* Unmap. */
|
||||
addr = (const u_char *)addr + sizeof mapped;
|
||||
uaddr += sizeof mapped;
|
||||
af = AF_INET;
|
||||
len = INADDRSZ;
|
||||
}
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
size = INADDRSZ;
|
||||
break;
|
||||
case AF_INET6:
|
||||
size = IN6ADDRSZ;
|
||||
break;
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
if (size > len) {
|
||||
errno = EINVAL;
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the search.
|
||||
*/
|
||||
ho_rewind(this);
|
||||
while ((hp = ho_next(this)) != NULL) {
|
||||
char **hap;
|
||||
|
||||
for (hap = hp->h_addr_list; *hap; hap++) {
|
||||
const u_char *taddr = (const u_char *)*hap;
|
||||
int taf = hp->h_addrtype;
|
||||
int tlen = hp->h_length;
|
||||
|
||||
if (taf == AF_INET6 && tlen == IN6ADDRSZ &&
|
||||
(!memcmp(taddr, mapped, sizeof mapped) ||
|
||||
!memcmp(taddr, tunnelled, sizeof tunnelled))) {
|
||||
/* Unmap. */
|
||||
taddr += sizeof mapped;
|
||||
taf = AF_INET;
|
||||
tlen = INADDRSZ;
|
||||
}
|
||||
if (taf == af && tlen == len &&
|
||||
!memcmp(taddr, uaddr, tlen))
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found:
|
||||
if (!hp) {
|
||||
RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
|
||||
return (NULL);
|
||||
}
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
|
||||
return (hp);
|
||||
}
|
||||
|
||||
static struct hostent *
|
||||
ho_next(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char *cp, **q, *p;
|
||||
char *bufp, *ndbuf, *dbuf = NULL;
|
||||
int c, af, len, bufsiz, offset;
|
||||
|
||||
if (init(this) == -1)
|
||||
return (NULL);
|
||||
|
||||
if (!pvt->fp)
|
||||
ho_rewind(this);
|
||||
if (!pvt->fp) {
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
bufp = pvt->hostbuf;
|
||||
bufsiz = sizeof pvt->hostbuf;
|
||||
offset = 0;
|
||||
again:
|
||||
if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) {
|
||||
RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
|
||||
if (dbuf)
|
||||
free(dbuf);
|
||||
return (NULL);
|
||||
}
|
||||
if (!strchr(p, '\n') && !feof(pvt->fp)) {
|
||||
#define GROWBUF 1024
|
||||
/* allocate space for longer line */
|
||||
if (dbuf == NULL) {
|
||||
if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL)
|
||||
strcpy(ndbuf, bufp);
|
||||
} else
|
||||
ndbuf = realloc(dbuf, bufsiz + GROWBUF);
|
||||
if (ndbuf) {
|
||||
dbuf = ndbuf;
|
||||
bufp = dbuf;
|
||||
bufsiz += GROWBUF;
|
||||
offset = strlen(dbuf);
|
||||
} else {
|
||||
/* allocation failed; skip this long line */
|
||||
while ((c = getc(pvt->fp)) != EOF)
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c != EOF)
|
||||
ungetc(c, pvt->fp);
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
|
||||
p -= offset;
|
||||
offset = 0;
|
||||
|
||||
if (*p == '#')
|
||||
goto again;
|
||||
if ((cp = strpbrk(p, "#\n")) != NULL)
|
||||
*cp = '\0';
|
||||
if (!(cp = strpbrk(p, " \t")))
|
||||
goto again;
|
||||
*cp++ = '\0';
|
||||
if (inet_pton(AF_INET6, p, pvt->host_addr) > 0) {
|
||||
af = AF_INET6;
|
||||
len = IN6ADDRSZ;
|
||||
} else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) {
|
||||
if (pvt->res->options & RES_USE_INET6) {
|
||||
map_v4v6_address((char*)pvt->host_addr,
|
||||
(char*)pvt->host_addr);
|
||||
af = AF_INET6;
|
||||
len = IN6ADDRSZ;
|
||||
} else {
|
||||
af = AF_INET;
|
||||
len = INADDRSZ;
|
||||
}
|
||||
} else {
|
||||
goto again;
|
||||
}
|
||||
pvt->h_addr_ptrs[0] = (char *)pvt->host_addr;
|
||||
pvt->h_addr_ptrs[1] = NULL;
|
||||
pvt->host.h_addr_list = pvt->h_addr_ptrs;
|
||||
pvt->host.h_length = len;
|
||||
pvt->host.h_addrtype = af;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
pvt->host.h_name = cp;
|
||||
q = pvt->host.h_aliases = pvt->host_aliases;
|
||||
if ((cp = strpbrk(cp, " \t")) != NULL)
|
||||
*cp++ = '\0';
|
||||
while (cp && *cp) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (q < &pvt->host_aliases[MAXALIASES - 1])
|
||||
*q++ = cp;
|
||||
if ((cp = strpbrk(cp, " \t")) != NULL)
|
||||
*cp++ = '\0';
|
||||
}
|
||||
*q = NULL;
|
||||
if (dbuf)
|
||||
free(dbuf);
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
|
||||
return (&pvt->host);
|
||||
}
|
||||
|
||||
static void
|
||||
ho_rewind(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp) {
|
||||
if (fseek(pvt->fp, 0L, SEEK_SET) == 0)
|
||||
return;
|
||||
(void)fclose(pvt->fp);
|
||||
}
|
||||
if (!(pvt->fp = fopen(_PATH_HOSTS, "r")))
|
||||
return;
|
||||
if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) {
|
||||
(void)fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ho_minimize(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp != NULL) {
|
||||
(void)fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
if (pvt->res)
|
||||
res_nclose(pvt->res);
|
||||
}
|
||||
|
||||
static struct __res_state *
|
||||
ho_res_get(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (!res) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof *res);
|
||||
ho_res_set(this, res, free);
|
||||
}
|
||||
|
||||
return (pvt->res);
|
||||
}
|
||||
|
||||
static void
|
||||
ho_res_set(struct irs_ho *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->res && pvt->free_res) {
|
||||
res_nclose(pvt->res);
|
||||
(*pvt->free_res)(pvt->res);
|
||||
}
|
||||
|
||||
pvt->res = res;
|
||||
pvt->free_res = free_res;
|
||||
}
|
||||
|
||||
struct lcl_res_target {
|
||||
struct lcl_res_target *next;
|
||||
int family;
|
||||
};
|
||||
|
||||
/* XXX */
|
||||
extern struct addrinfo *hostent2addrinfo __P((struct hostent *,
|
||||
const struct addrinfo *pai));
|
||||
|
||||
static struct addrinfo *
|
||||
ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai)
|
||||
{
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct hostent *hp;
|
||||
struct lcl_res_target q, q2, *p;
|
||||
struct addrinfo sentinel, *cur;
|
||||
|
||||
memset(&q, 0, sizeof(q2));
|
||||
memset(&q2, 0, sizeof(q2));
|
||||
memset(&sentinel, 0, sizeof(sentinel));
|
||||
cur = &sentinel;
|
||||
|
||||
switch(pai->ai_family) {
|
||||
case AF_UNSPEC: /* INET6 then INET4 */
|
||||
q.family = AF_INET6;
|
||||
q.next = &q2;
|
||||
q2.family = AF_INET;
|
||||
break;
|
||||
case AF_INET6:
|
||||
q.family = AF_INET6;
|
||||
break;
|
||||
case AF_INET:
|
||||
q.family = AF_INET;
|
||||
break;
|
||||
default:
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
for (p = &q; p; p = p->next) {
|
||||
struct addrinfo *ai;
|
||||
|
||||
hp = (*this->byname2)(this, name, p->family);
|
||||
if (hp == NULL) {
|
||||
/* byname2 should've set an appropriate error */
|
||||
continue;
|
||||
}
|
||||
if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
|
||||
(hp->h_addr_list[0] == NULL)) {
|
||||
RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
|
||||
continue;
|
||||
}
|
||||
|
||||
ai = hostent2addrinfo(hp, pai);
|
||||
if (ai) {
|
||||
cur->ai_next = ai;
|
||||
while (cur && cur->ai_next)
|
||||
cur = cur->ai_next;
|
||||
}
|
||||
}
|
||||
|
||||
if (sentinel.ai_next == NULL)
|
||||
RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
|
||||
|
||||
return(sentinel.ai_next);
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
static size_t
|
||||
ns_namelen(const char *s) {
|
||||
int i;
|
||||
|
||||
for (i = strlen(s); i > 0 && s[i-1] == '.'; i--)
|
||||
(void)NULL;
|
||||
return ((size_t) i);
|
||||
}
|
||||
|
||||
static int
|
||||
init(struct irs_ho *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res && !ho_res_get(this))
|
||||
return (-1);
|
||||
if (((pvt->res->options & RES_INIT) == 0U) &&
|
||||
res_ninit(pvt->res) == -1)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
@@ -1,444 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "lcl_p.h"
|
||||
|
||||
/* Definitions */
|
||||
|
||||
#define NG_HOST 0 /* Host name */
|
||||
#define NG_USER 1 /* User name */
|
||||
#define NG_DOM 2 /* and Domain name */
|
||||
#define LINSIZ 1024 /* Length of netgroup file line */
|
||||
|
||||
/*
|
||||
* XXX Warning XXX
|
||||
* This code is a hack-and-slash special. It realy needs to be
|
||||
* rewritten with things like strdup, and realloc in mind.
|
||||
* More reasonable data structures would not be a bad thing.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Static Variables and functions used by setnetgrent(), getnetgrent() and
|
||||
* endnetgrent().
|
||||
* There are two linked lists:
|
||||
* - linelist is just used by setnetgrent() to parse the net group file via.
|
||||
* parse_netgrp()
|
||||
* - netgrp is the list of entries for the current netgroup
|
||||
*/
|
||||
struct linelist {
|
||||
struct linelist *l_next; /* Chain ptr. */
|
||||
int l_parsed; /* Flag for cycles */
|
||||
char * l_groupname; /* Name of netgroup */
|
||||
char * l_line; /* Netgroup entrie(s) to be parsed */
|
||||
};
|
||||
|
||||
struct ng_old_struct {
|
||||
struct ng_old_struct *ng_next; /* Chain ptr */
|
||||
char * ng_str[3]; /* Field pointers, see below */
|
||||
};
|
||||
|
||||
struct pvt {
|
||||
FILE *fp;
|
||||
struct linelist *linehead;
|
||||
struct ng_old_struct *nextgrp;
|
||||
struct {
|
||||
struct ng_old_struct *gr;
|
||||
char *grname;
|
||||
} grouphead;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void ng_rewind(struct irs_ng *, const char*);
|
||||
static void ng_close(struct irs_ng *);
|
||||
static int ng_next(struct irs_ng *, const char **,
|
||||
const char **, const char **);
|
||||
static int ng_test(struct irs_ng *, const char *,
|
||||
const char *, const char *,
|
||||
const char *);
|
||||
static void ng_minimize(struct irs_ng *);
|
||||
|
||||
static int parse_netgrp(struct irs_ng *, const char*);
|
||||
static struct linelist *read_for_group(struct irs_ng *, const char *);
|
||||
static void freelists(struct irs_ng *);
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_ng *
|
||||
irs_lcl_ng(struct irs_acc *this) {
|
||||
struct irs_ng *ng;
|
||||
struct pvt *pvt;
|
||||
|
||||
UNUSED(this);
|
||||
|
||||
if (!(ng = memget(sizeof *ng))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(ng, 0x5e, sizeof *ng);
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
memput(ng, sizeof *ng);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
ng->private = pvt;
|
||||
ng->close = ng_close;
|
||||
ng->next = ng_next;
|
||||
ng->test = ng_test;
|
||||
ng->rewind = ng_rewind;
|
||||
ng->minimize = ng_minimize;
|
||||
return (ng);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
ng_close(struct irs_ng *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp != NULL)
|
||||
fclose(pvt->fp);
|
||||
freelists(this);
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the netgroup file looking for the netgroup and build the list
|
||||
* of netgrp structures. Let parse_netgrp() and read_for_group() do
|
||||
* most of the work.
|
||||
*/
|
||||
static void
|
||||
ng_rewind(struct irs_ng *this, const char *group) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) {
|
||||
fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
|
||||
if (pvt->fp == NULL || pvt->grouphead.gr == NULL ||
|
||||
strcmp(group, pvt->grouphead.grname)) {
|
||||
freelists(this);
|
||||
if (pvt->fp != NULL)
|
||||
fclose(pvt->fp);
|
||||
pvt->fp = fopen(_PATH_NETGROUP, "r");
|
||||
if (pvt->fp != NULL) {
|
||||
if (parse_netgrp(this, group))
|
||||
freelists(this);
|
||||
if (!(pvt->grouphead.grname = strdup(group)))
|
||||
freelists(this);
|
||||
fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
}
|
||||
pvt->nextgrp = pvt->grouphead.gr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next netgroup off the list.
|
||||
*/
|
||||
static int
|
||||
ng_next(struct irs_ng *this, const char **host, const char **user,
|
||||
const char **domain)
|
||||
{
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->nextgrp) {
|
||||
*host = pvt->nextgrp->ng_str[NG_HOST];
|
||||
*user = pvt->nextgrp->ng_str[NG_USER];
|
||||
*domain = pvt->nextgrp->ng_str[NG_DOM];
|
||||
pvt->nextgrp = pvt->nextgrp->ng_next;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a match in a netgroup.
|
||||
*/
|
||||
static int
|
||||
ng_test(struct irs_ng *this, const char *name,
|
||||
const char *host, const char *user, const char *domain)
|
||||
{
|
||||
const char *ng_host, *ng_user, *ng_domain;
|
||||
|
||||
ng_rewind(this, name);
|
||||
while (ng_next(this, &ng_host, &ng_user, &ng_domain))
|
||||
if ((host == NULL || ng_host == NULL ||
|
||||
!strcmp(host, ng_host)) &&
|
||||
(user == NULL || ng_user == NULL ||
|
||||
!strcmp(user, ng_user)) &&
|
||||
(domain == NULL || ng_domain == NULL ||
|
||||
!strcmp(domain, ng_domain))) {
|
||||
freelists(this);
|
||||
return (1);
|
||||
}
|
||||
freelists(this);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ng_minimize(struct irs_ng *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp != NULL) {
|
||||
(void)fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Private */
|
||||
|
||||
/*
|
||||
* endnetgrent() - cleanup
|
||||
*/
|
||||
static void
|
||||
freelists(struct irs_ng *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct linelist *lp, *olp;
|
||||
struct ng_old_struct *gp, *ogp;
|
||||
|
||||
lp = pvt->linehead;
|
||||
while (lp) {
|
||||
olp = lp;
|
||||
lp = lp->l_next;
|
||||
free(olp->l_groupname);
|
||||
free(olp->l_line);
|
||||
free((char *)olp);
|
||||
}
|
||||
pvt->linehead = NULL;
|
||||
if (pvt->grouphead.grname) {
|
||||
free(pvt->grouphead.grname);
|
||||
pvt->grouphead.grname = NULL;
|
||||
}
|
||||
gp = pvt->grouphead.gr;
|
||||
while (gp) {
|
||||
ogp = gp;
|
||||
gp = gp->ng_next;
|
||||
if (ogp->ng_str[NG_HOST])
|
||||
free(ogp->ng_str[NG_HOST]);
|
||||
if (ogp->ng_str[NG_USER])
|
||||
free(ogp->ng_str[NG_USER]);
|
||||
if (ogp->ng_str[NG_DOM])
|
||||
free(ogp->ng_str[NG_DOM]);
|
||||
free((char *)ogp);
|
||||
}
|
||||
pvt->grouphead.gr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the netgroup file setting up the linked lists.
|
||||
*/
|
||||
static int
|
||||
parse_netgrp(struct irs_ng *this, const char *group) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char *spos, *epos;
|
||||
int len, strpos;
|
||||
char *pos, *gpos;
|
||||
struct ng_old_struct *grp;
|
||||
struct linelist *lp = pvt->linehead;
|
||||
|
||||
/*
|
||||
* First, see if the line has already been read in.
|
||||
*/
|
||||
while (lp) {
|
||||
if (!strcmp(group, lp->l_groupname))
|
||||
break;
|
||||
lp = lp->l_next;
|
||||
}
|
||||
if (lp == NULL &&
|
||||
(lp = read_for_group(this, group)) == NULL)
|
||||
return (1);
|
||||
if (lp->l_parsed) {
|
||||
/*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/
|
||||
return (1);
|
||||
} else
|
||||
lp->l_parsed = 1;
|
||||
pos = lp->l_line;
|
||||
while (*pos != '\0') {
|
||||
if (*pos == '(') {
|
||||
if (!(grp = malloc(sizeof (struct ng_old_struct)))) {
|
||||
freelists(this);
|
||||
errno = ENOMEM;
|
||||
return (1);
|
||||
}
|
||||
memset(grp, 0, sizeof (struct ng_old_struct));
|
||||
grp->ng_next = pvt->grouphead.gr;
|
||||
pvt->grouphead.gr = grp;
|
||||
pos++;
|
||||
gpos = strsep(&pos, ")");
|
||||
for (strpos = 0; strpos < 3; strpos++) {
|
||||
if ((spos = strsep(&gpos, ","))) {
|
||||
while (*spos == ' ' || *spos == '\t')
|
||||
spos++;
|
||||
if ((epos = strpbrk(spos, " \t"))) {
|
||||
*epos = '\0';
|
||||
len = epos - spos;
|
||||
} else
|
||||
len = strlen(spos);
|
||||
if (len > 0) {
|
||||
if(!(grp->ng_str[strpos]
|
||||
= (char *)
|
||||
malloc(len + 1))) {
|
||||
freelists(this);
|
||||
return (1);
|
||||
}
|
||||
memcpy(grp->ng_str[strpos],
|
||||
spos,
|
||||
len + 1);
|
||||
}
|
||||
} else
|
||||
goto errout;
|
||||
}
|
||||
} else {
|
||||
spos = strsep(&pos, ", \t");
|
||||
if (spos != NULL && parse_netgrp(this, spos)) {
|
||||
freelists(this);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
if (pos == NULL)
|
||||
break;
|
||||
while (*pos == ' ' || *pos == ',' || *pos == '\t')
|
||||
pos++;
|
||||
}
|
||||
return (0);
|
||||
errout:
|
||||
/*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
|
||||
spos);*/
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the netgroup file and save lines until the line for the netgroup
|
||||
* is found. Return 1 if eof is encountered.
|
||||
*/
|
||||
static struct linelist *
|
||||
read_for_group(struct irs_ng *this, const char *group) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char *pos, *spos, *linep = NULL, *olinep;
|
||||
int len, olen, cont;
|
||||
struct linelist *lp;
|
||||
char line[LINSIZ + 1];
|
||||
|
||||
while (fgets(line, LINSIZ, pvt->fp) != NULL) {
|
||||
pos = line;
|
||||
if (*pos == '#')
|
||||
continue;
|
||||
while (*pos == ' ' || *pos == '\t')
|
||||
pos++;
|
||||
spos = pos;
|
||||
while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
|
||||
*pos != '\0')
|
||||
pos++;
|
||||
len = pos - spos;
|
||||
while (*pos == ' ' || *pos == '\t')
|
||||
pos++;
|
||||
if (*pos != '\n' && *pos != '\0') {
|
||||
if (!(lp = malloc(sizeof (*lp)))) {
|
||||
freelists(this);
|
||||
return (NULL);
|
||||
}
|
||||
lp->l_parsed = 0;
|
||||
if (!(lp->l_groupname = malloc(len + 1))) {
|
||||
free(lp);
|
||||
freelists(this);
|
||||
return (NULL);
|
||||
}
|
||||
memcpy(lp->l_groupname, spos, len);
|
||||
*(lp->l_groupname + len) = '\0';
|
||||
len = strlen(pos);
|
||||
olen = 0;
|
||||
olinep = NULL;
|
||||
|
||||
/*
|
||||
* Loop around handling line continuations.
|
||||
*/
|
||||
do {
|
||||
if (*(pos + len - 1) == '\n')
|
||||
len--;
|
||||
if (*(pos + len - 1) == '\\') {
|
||||
len--;
|
||||
cont = 1;
|
||||
} else
|
||||
cont = 0;
|
||||
if (len > 0) {
|
||||
if (!(linep = malloc(olen + len + 1))){
|
||||
if (olen > 0)
|
||||
free(olinep);
|
||||
free(lp->l_groupname);
|
||||
free(lp);
|
||||
freelists(this);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
if (olen > 0) {
|
||||
memcpy(linep, olinep, olen);
|
||||
free(olinep);
|
||||
}
|
||||
memcpy(linep + olen, pos, len);
|
||||
olen += len;
|
||||
*(linep + olen) = '\0';
|
||||
olinep = linep;
|
||||
}
|
||||
if (cont) {
|
||||
if (fgets(line, LINSIZ, pvt->fp)) {
|
||||
pos = line;
|
||||
len = strlen(pos);
|
||||
} else
|
||||
cont = 0;
|
||||
}
|
||||
} while (cont);
|
||||
lp->l_line = linep;
|
||||
lp->l_next = pvt->linehead;
|
||||
pvt->linehead = lp;
|
||||
|
||||
/*
|
||||
* If this is the one we wanted, we are done.
|
||||
*/
|
||||
if (!strcmp(lp->l_groupname, group))
|
||||
return (lp);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */
|
||||
/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include <isc/misc.h>
|
||||
#include "irs_p.h"
|
||||
#include "lcl_p.h"
|
||||
|
||||
#define MAXALIASES 35
|
||||
#define MAXADDRSIZE 4
|
||||
|
||||
struct pvt {
|
||||
FILE * fp;
|
||||
char line[BUFSIZ+1];
|
||||
struct nwent net;
|
||||
char * aliases[MAXALIASES];
|
||||
char addr[MAXADDRSIZE];
|
||||
struct __res_state * res;
|
||||
void (*free_res)(void *);
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void nw_close(struct irs_nw *);
|
||||
static struct nwent * nw_byname(struct irs_nw *, const char *, int);
|
||||
static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int);
|
||||
static struct nwent * nw_next(struct irs_nw *);
|
||||
static void nw_rewind(struct irs_nw *);
|
||||
static void nw_minimize(struct irs_nw *);
|
||||
static struct __res_state * nw_res_get(struct irs_nw *this);
|
||||
static void nw_res_set(struct irs_nw *this,
|
||||
struct __res_state *res,
|
||||
void (*free_res)(void *));
|
||||
|
||||
static int init(struct irs_nw *this);
|
||||
|
||||
/* Portability. */
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_nw *
|
||||
irs_lcl_nw(struct irs_acc *this) {
|
||||
struct irs_nw *nw;
|
||||
struct pvt *pvt;
|
||||
|
||||
UNUSED(this);
|
||||
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
if (!(nw = memget(sizeof *nw))) {
|
||||
memput(pvt, sizeof *pvt);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(nw, 0x5e, sizeof *nw);
|
||||
nw->private = pvt;
|
||||
nw->close = nw_close;
|
||||
nw->byname = nw_byname;
|
||||
nw->byaddr = nw_byaddr;
|
||||
nw->next = nw_next;
|
||||
nw->rewind = nw_rewind;
|
||||
nw->minimize = nw_minimize;
|
||||
nw->res_get = nw_res_get;
|
||||
nw->res_set = nw_res_set;
|
||||
return (nw);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
nw_close(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
nw_minimize(this);
|
||||
if (pvt->res && pvt->free_res)
|
||||
(*pvt->free_res)(pvt->res);
|
||||
if (pvt->fp)
|
||||
(void)fclose(pvt->fp);
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_byaddr(struct irs_nw *this, void *net, int length, int type) {
|
||||
struct nwent *p;
|
||||
|
||||
if (init(this) == -1)
|
||||
return(NULL);
|
||||
|
||||
nw_rewind(this);
|
||||
while ((p = nw_next(this)) != NULL)
|
||||
if (p->n_addrtype == type && p->n_length == length)
|
||||
if (bitncmp(p->n_addr, net, length) == 0)
|
||||
break;
|
||||
return (p);
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_byname(struct irs_nw *this, const char *name, int type) {
|
||||
struct nwent *p;
|
||||
char **ap;
|
||||
|
||||
if (init(this) == -1)
|
||||
return(NULL);
|
||||
|
||||
nw_rewind(this);
|
||||
while ((p = nw_next(this)) != NULL) {
|
||||
if (ns_samename(p->n_name, name) == 1 &&
|
||||
p->n_addrtype == type)
|
||||
break;
|
||||
for (ap = p->n_aliases; *ap; ap++)
|
||||
if ((ns_samename(*ap, name) == 1) &&
|
||||
(p->n_addrtype == type))
|
||||
goto found;
|
||||
}
|
||||
found:
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void
|
||||
nw_rewind(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp) {
|
||||
if (fseek(pvt->fp, 0L, SEEK_SET) == 0)
|
||||
return;
|
||||
(void)fclose(pvt->fp);
|
||||
}
|
||||
if (!(pvt->fp = fopen(_PATH_NETWORKS, "r")))
|
||||
return;
|
||||
if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) {
|
||||
(void)fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct nwent *
|
||||
nw_next(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
struct nwent *ret = NULL;
|
||||
char *p, *cp, **q;
|
||||
char *bufp, *ndbuf, *dbuf = NULL;
|
||||
int c, bufsiz, offset = 0;
|
||||
|
||||
if (init(this) == -1)
|
||||
return(NULL);
|
||||
|
||||
if (pvt->fp == NULL)
|
||||
nw_rewind(this);
|
||||
if (pvt->fp == NULL) {
|
||||
RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
|
||||
return (NULL);
|
||||
}
|
||||
bufp = pvt->line;
|
||||
bufsiz = sizeof(pvt->line);
|
||||
|
||||
again:
|
||||
p = fgets(bufp + offset, bufsiz - offset, pvt->fp);
|
||||
if (p == NULL)
|
||||
goto cleanup;
|
||||
if (!strchr(p, '\n') && !feof(pvt->fp)) {
|
||||
#define GROWBUF 1024
|
||||
/* allocate space for longer line */
|
||||
if (dbuf == NULL) {
|
||||
if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL)
|
||||
strcpy(ndbuf, bufp);
|
||||
} else
|
||||
ndbuf = realloc(dbuf, bufsiz + GROWBUF);
|
||||
if (ndbuf) {
|
||||
dbuf = ndbuf;
|
||||
bufp = dbuf;
|
||||
bufsiz += GROWBUF;
|
||||
offset = strlen(dbuf);
|
||||
} else {
|
||||
/* allocation failed; skip this long line */
|
||||
while ((c = getc(pvt->fp)) != EOF)
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c != EOF)
|
||||
ungetc(c, pvt->fp);
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
|
||||
p -= offset;
|
||||
offset = 0;
|
||||
|
||||
if (*p == '#')
|
||||
goto again;
|
||||
|
||||
cp = strpbrk(p, "#\n");
|
||||
if (cp != NULL)
|
||||
*cp = '\0';
|
||||
pvt->net.n_name = p;
|
||||
cp = strpbrk(p, " \t");
|
||||
if (cp == NULL)
|
||||
goto again;
|
||||
*cp++ = '\0';
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
p = strpbrk(cp, " \t");
|
||||
if (p != NULL)
|
||||
*p++ = '\0';
|
||||
pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr,
|
||||
sizeof pvt->addr);
|
||||
if (pvt->net.n_length < 0)
|
||||
goto again;
|
||||
pvt->net.n_addrtype = AF_INET;
|
||||
pvt->net.n_addr = pvt->addr;
|
||||
q = pvt->net.n_aliases = pvt->aliases;
|
||||
if (p != NULL) {
|
||||
cp = p;
|
||||
while (cp && *cp) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (q < &pvt->aliases[MAXALIASES - 1])
|
||||
*q++ = cp;
|
||||
cp = strpbrk(cp, " \t");
|
||||
if (cp != NULL)
|
||||
*cp++ = '\0';
|
||||
}
|
||||
}
|
||||
*q = NULL;
|
||||
ret = &pvt->net;
|
||||
|
||||
cleanup:
|
||||
if (dbuf)
|
||||
free(dbuf);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
nw_minimize(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->res)
|
||||
res_nclose(pvt->res);
|
||||
if (pvt->fp != NULL) {
|
||||
(void)fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct __res_state *
|
||||
nw_res_get(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (!res) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof *res);
|
||||
nw_res_set(this, res, free);
|
||||
}
|
||||
|
||||
return (pvt->res);
|
||||
}
|
||||
|
||||
static void
|
||||
nw_res_set(struct irs_nw *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->res && pvt->free_res) {
|
||||
res_nclose(pvt->res);
|
||||
(*pvt->free_res)(pvt->res);
|
||||
}
|
||||
|
||||
pvt->res = res;
|
||||
pvt->free_res = free_res;
|
||||
}
|
||||
|
||||
static int
|
||||
init(struct irs_nw *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (!pvt->res && !nw_res_get(this))
|
||||
return (-1);
|
||||
if (((pvt->res->options & RES_INIT) == 0U) &&
|
||||
res_ninit(pvt->res) == -1)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* lcl_p.h - private include file for the local accessor functions.
|
||||
*/
|
||||
|
||||
#ifndef _LCL_P_H_INCLUDED
|
||||
#define _LCL_P_H_INCLUDED
|
||||
|
||||
/*
|
||||
* Object state.
|
||||
*/
|
||||
struct lcl_p {
|
||||
struct __res_state * res;
|
||||
void (*free_res) __P((void *));
|
||||
};
|
||||
|
||||
/*
|
||||
* Externs.
|
||||
*/
|
||||
|
||||
extern struct irs_acc * irs_lcl_acc __P((const char *));
|
||||
extern struct irs_gr * irs_lcl_gr __P((struct irs_acc *));
|
||||
extern struct irs_pw * irs_lcl_pw __P((struct irs_acc *));
|
||||
extern struct irs_sv * irs_lcl_sv __P((struct irs_acc *));
|
||||
extern struct irs_pr * irs_lcl_pr __P((struct irs_acc *));
|
||||
extern struct irs_ho * irs_lcl_ho __P((struct irs_acc *));
|
||||
extern struct irs_nw * irs_lcl_nw __P((struct irs_acc *));
|
||||
extern struct irs_ng * irs_lcl_ng __P((struct irs_acc *));
|
||||
|
||||
#endif /*_LCL_P_H_INCLUDED*/
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* extern */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "lcl_p.h"
|
||||
|
||||
#ifndef _PATH_PROTOCOLS
|
||||
#define _PATH_PROTOCOLS "/etc/protocols"
|
||||
#endif
|
||||
#define MAXALIASES 35
|
||||
|
||||
/* Types */
|
||||
|
||||
struct pvt {
|
||||
FILE * fp;
|
||||
char line[BUFSIZ+1];
|
||||
struct protoent proto;
|
||||
char * proto_aliases[MAXALIASES];
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void pr_close(struct irs_pr *);
|
||||
static struct protoent * pr_next(struct irs_pr *);
|
||||
static struct protoent * pr_byname(struct irs_pr *, const char *);
|
||||
static struct protoent * pr_bynumber(struct irs_pr *, int);
|
||||
static void pr_rewind(struct irs_pr *);
|
||||
static void pr_minimize(struct irs_pr *);
|
||||
|
||||
/* Portability. */
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_pr *
|
||||
irs_lcl_pr(struct irs_acc *this) {
|
||||
struct irs_pr *pr;
|
||||
struct pvt *pvt;
|
||||
|
||||
if (!(pr = memget(sizeof *pr))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
if (!(pvt = memget(sizeof *pvt))) {
|
||||
memput(pr, sizeof *this);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
pr->private = pvt;
|
||||
pr->close = pr_close;
|
||||
pr->byname = pr_byname;
|
||||
pr->bynumber = pr_bynumber;
|
||||
pr->next = pr_next;
|
||||
pr->rewind = pr_rewind;
|
||||
pr->minimize = pr_minimize;
|
||||
pr->res_get = NULL;
|
||||
pr->res_set = NULL;
|
||||
return (pr);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
pr_close(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp)
|
||||
(void) fclose(pvt->fp);
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_byname(struct irs_pr *this, const char *name) {
|
||||
|
||||
struct protoent *p;
|
||||
char **cp;
|
||||
|
||||
pr_rewind(this);
|
||||
while ((p = pr_next(this))) {
|
||||
if (!strcmp(p->p_name, name))
|
||||
goto found;
|
||||
for (cp = p->p_aliases; *cp; cp++)
|
||||
if (!strcmp(*cp, name))
|
||||
goto found;
|
||||
}
|
||||
found:
|
||||
return (p);
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_bynumber(struct irs_pr *this, int proto) {
|
||||
struct protoent *p;
|
||||
|
||||
pr_rewind(this);
|
||||
while ((p = pr_next(this)))
|
||||
if (p->p_proto == proto)
|
||||
break;
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_rewind(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp) {
|
||||
if (fseek(pvt->fp, 0L, SEEK_SET) == 0)
|
||||
return;
|
||||
(void)fclose(pvt->fp);
|
||||
}
|
||||
if (!(pvt->fp = fopen(_PATH_PROTOCOLS, "r" )))
|
||||
return;
|
||||
if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) {
|
||||
(void)fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct protoent *
|
||||
pr_next(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
char *p, *cp, **q;
|
||||
char *bufp, *ndbuf, *dbuf = NULL;
|
||||
int c, bufsiz, offset;
|
||||
|
||||
if (!pvt->fp)
|
||||
pr_rewind(this);
|
||||
if (!pvt->fp)
|
||||
return (NULL);
|
||||
bufp = pvt->line;
|
||||
bufsiz = BUFSIZ;
|
||||
offset = 0;
|
||||
again:
|
||||
if ((p = fgets(bufp + offset, bufsiz - offset, pvt->fp)) == NULL) {
|
||||
if (dbuf)
|
||||
free(dbuf);
|
||||
return (NULL);
|
||||
}
|
||||
if (!strchr(p, '\n') && !feof(pvt->fp)) {
|
||||
#define GROWBUF 1024
|
||||
/* allocate space for longer line */
|
||||
if (dbuf == NULL) {
|
||||
if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL)
|
||||
strcpy(ndbuf, bufp);
|
||||
} else
|
||||
ndbuf = realloc(dbuf, bufsiz + GROWBUF);
|
||||
if (ndbuf) {
|
||||
dbuf = ndbuf;
|
||||
bufp = dbuf;
|
||||
bufsiz += GROWBUF;
|
||||
offset = strlen(dbuf);
|
||||
} else {
|
||||
/* allocation failed; skip this long line */
|
||||
while ((c = getc(pvt->fp)) != EOF)
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c != EOF)
|
||||
ungetc(c, pvt->fp);
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
|
||||
p -= offset;
|
||||
offset = 0;
|
||||
|
||||
if (*p == '#')
|
||||
goto again;
|
||||
cp = strpbrk(p, "#\n");
|
||||
if (cp != NULL)
|
||||
*cp = '\0';
|
||||
pvt->proto.p_name = p;
|
||||
cp = strpbrk(p, " \t");
|
||||
if (cp == NULL)
|
||||
goto again;
|
||||
*cp++ = '\0';
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
p = strpbrk(cp, " \t");
|
||||
if (p != NULL)
|
||||
*p++ = '\0';
|
||||
pvt->proto.p_proto = atoi(cp);
|
||||
q = pvt->proto.p_aliases = pvt->proto_aliases;
|
||||
if (p != NULL) {
|
||||
cp = p;
|
||||
while (cp && *cp) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (q < &pvt->proto_aliases[MAXALIASES - 1])
|
||||
*q++ = cp;
|
||||
cp = strpbrk(cp, " \t");
|
||||
if (cp != NULL)
|
||||
*cp++ = '\0';
|
||||
}
|
||||
}
|
||||
*q = NULL;
|
||||
return (&pvt->proto);
|
||||
}
|
||||
|
||||
static void
|
||||
pr_minimize(struct irs_pr *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->fp != NULL) {
|
||||
(void)fclose(pvt->fp);
|
||||
pvt->fp = NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,431 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* extern */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
#include <db.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "lcl_p.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) ((size_t)sprintf x)
|
||||
#endif
|
||||
|
||||
/* Types */
|
||||
|
||||
struct pvt {
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
DB * dbh;
|
||||
int dbf;
|
||||
#endif
|
||||
struct lcl_sv sv;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void sv_close(struct irs_sv*);
|
||||
static struct servent * sv_next(struct irs_sv *);
|
||||
static struct servent * sv_byname(struct irs_sv *, const char *,
|
||||
const char *);
|
||||
static struct servent * sv_byport(struct irs_sv *, int, const char *);
|
||||
static void sv_rewind(struct irs_sv *);
|
||||
static void sv_minimize(struct irs_sv *);
|
||||
/*global*/ struct servent * irs_lclsv_fnxt(struct lcl_sv *);
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
static struct servent * sv_db_rec(struct lcl_sv *, DBT *, DBT *);
|
||||
#endif
|
||||
|
||||
/* Portability */
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_sv *
|
||||
irs_lcl_sv(struct irs_acc *this) {
|
||||
struct irs_sv *sv;
|
||||
struct pvt *pvt;
|
||||
|
||||
UNUSED(this);
|
||||
|
||||
if ((sv = memget(sizeof *sv)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(sv, 0x5e, sizeof *sv);
|
||||
if ((pvt = memget(sizeof *pvt)) == NULL) {
|
||||
memput(sv, sizeof *sv);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(pvt, 0, sizeof *pvt);
|
||||
sv->private = pvt;
|
||||
sv->close = sv_close;
|
||||
sv->next = sv_next;
|
||||
sv->byname = sv_byname;
|
||||
sv->byport = sv_byport;
|
||||
sv->rewind = sv_rewind;
|
||||
sv->minimize = sv_minimize;
|
||||
sv->res_get = NULL;
|
||||
sv->res_set = NULL;
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
pvt->dbf = R_FIRST;
|
||||
#endif
|
||||
return (sv);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static void
|
||||
sv_close(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
if (pvt->dbh != NULL)
|
||||
(*pvt->dbh->close)(pvt->dbh);
|
||||
#endif
|
||||
if (pvt->sv.fp)
|
||||
fclose(pvt->sv.fp);
|
||||
memput(pvt, sizeof *pvt);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_byname(struct irs_sv *this, const char *name, const char *proto) {
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
#endif
|
||||
struct servent *p;
|
||||
char **cp;
|
||||
|
||||
sv_rewind(this);
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
if (pvt->dbh != NULL) {
|
||||
DBT key, data;
|
||||
|
||||
/* Note that (sizeof "/") == 2. */
|
||||
if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0)
|
||||
> sizeof pvt->sv.line)
|
||||
goto try_local;
|
||||
key.data = pvt->sv.line;
|
||||
key.size = SPRINTF((pvt->sv.line, "%s/%s", name,
|
||||
proto ? proto : "")) + 1;
|
||||
if (proto != NULL) {
|
||||
if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0)
|
||||
return (NULL);
|
||||
} else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR)
|
||||
!= 0)
|
||||
return (NULL);
|
||||
return (sv_db_rec(&pvt->sv, &key, &data));
|
||||
}
|
||||
try_local:
|
||||
#endif
|
||||
|
||||
while ((p = sv_next(this))) {
|
||||
if (strcmp(name, p->s_name) == 0)
|
||||
goto gotname;
|
||||
for (cp = p->s_aliases; *cp; cp++)
|
||||
if (strcmp(name, *cp) == 0)
|
||||
goto gotname;
|
||||
continue;
|
||||
gotname:
|
||||
if (proto == NULL || strcmp(p->s_proto, proto) == 0)
|
||||
break;
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_byport(struct irs_sv *this, int port, const char *proto) {
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
#endif
|
||||
struct servent *p;
|
||||
|
||||
sv_rewind(this);
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
if (pvt->dbh != NULL) {
|
||||
DBT key, data;
|
||||
u_short *ports;
|
||||
|
||||
ports = (u_short *)pvt->sv.line;
|
||||
ports[0] = 0;
|
||||
ports[1] = port;
|
||||
key.data = ports;
|
||||
key.size = sizeof(u_short) * 2;
|
||||
if (proto && *proto) {
|
||||
strncpy((char *)ports + key.size, proto,
|
||||
BUFSIZ - key.size);
|
||||
key.size += strlen((char *)ports + key.size) + 1;
|
||||
if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0)
|
||||
return (NULL);
|
||||
} else {
|
||||
if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR)
|
||||
!= 0)
|
||||
return (NULL);
|
||||
}
|
||||
return (sv_db_rec(&pvt->sv, &key, &data));
|
||||
}
|
||||
#endif
|
||||
while ((p = sv_next(this))) {
|
||||
if (p->s_port != port)
|
||||
continue;
|
||||
if (proto == NULL || strcmp(p->s_proto, proto) == 0)
|
||||
break;
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void
|
||||
sv_rewind(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
if (pvt->sv.fp) {
|
||||
if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0)
|
||||
return;
|
||||
(void)fclose(pvt->sv.fp);
|
||||
pvt->sv.fp = NULL;
|
||||
}
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
pvt->dbf = R_FIRST;
|
||||
if (pvt->dbh != NULL)
|
||||
return;
|
||||
pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL);
|
||||
if (pvt->dbh != NULL) {
|
||||
if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) {
|
||||
(*pvt->dbh->close)(pvt->dbh);
|
||||
pvt->dbh = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL)
|
||||
return;
|
||||
if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) {
|
||||
(void)fclose(pvt->sv.fp);
|
||||
pvt->sv.fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct servent *
|
||||
sv_next(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
if (pvt->dbh == NULL && pvt->sv.fp == NULL)
|
||||
#else
|
||||
if (pvt->sv.fp == NULL)
|
||||
#endif
|
||||
sv_rewind(this);
|
||||
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
if (pvt->dbh != NULL) {
|
||||
DBT key, data;
|
||||
|
||||
while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){
|
||||
pvt->dbf = R_NEXT;
|
||||
if (((char *)key.data)[0])
|
||||
continue;
|
||||
return (sv_db_rec(&pvt->sv, &key, &data));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pvt->sv.fp == NULL)
|
||||
return (NULL);
|
||||
return (irs_lclsv_fnxt(&pvt->sv));
|
||||
}
|
||||
|
||||
static void
|
||||
sv_minimize(struct irs_sv *this) {
|
||||
struct pvt *pvt = (struct pvt *)this->private;
|
||||
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
if (pvt->dbh != NULL) {
|
||||
(*pvt->dbh->close)(pvt->dbh);
|
||||
pvt->dbh = NULL;
|
||||
}
|
||||
#endif
|
||||
if (pvt->sv.fp != NULL) {
|
||||
(void)fclose(pvt->sv.fp);
|
||||
pvt->sv.fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Quasipublic. */
|
||||
|
||||
struct servent *
|
||||
irs_lclsv_fnxt(struct lcl_sv *sv) {
|
||||
char *p, *cp, **q;
|
||||
|
||||
again:
|
||||
if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL)
|
||||
return (NULL);
|
||||
if (*p == '#')
|
||||
goto again;
|
||||
sv->serv.s_name = p;
|
||||
while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
|
||||
++p;
|
||||
if (*p == '\0' || *p == '#' || *p == '\n')
|
||||
goto again;
|
||||
*p++ = '\0';
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
if (*p == '\0' || *p == '#' || *p == '\n')
|
||||
goto again;
|
||||
sv->serv.s_port = htons((u_short)strtol(p, &cp, 10));
|
||||
if (cp == p || (*cp != '/' && *cp != ','))
|
||||
goto again;
|
||||
p = cp + 1;
|
||||
sv->serv.s_proto = p;
|
||||
|
||||
q = sv->serv.s_aliases = sv->serv_aliases;
|
||||
|
||||
while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
|
||||
++p;
|
||||
|
||||
while (*p == ' ' || *p == '\t') {
|
||||
*p++ = '\0';
|
||||
while (*p == ' ' || *p == '\t')
|
||||
++p;
|
||||
if (*p == '\0' || *p == '#' || *p == '\n')
|
||||
break;
|
||||
if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1])
|
||||
*q++ = p;
|
||||
while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
|
||||
++p;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
*q = NULL;
|
||||
return (&sv->serv);
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
static struct servent *
|
||||
sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) {
|
||||
char *p, **q;
|
||||
int n;
|
||||
|
||||
p = data->data;
|
||||
p[data->size - 1] = '\0'; /* should be, but we depend on it */
|
||||
|
||||
if (((char *)key->data)[0] == '\0') {
|
||||
if (key->size < sizeof(u_short)*2 || data->size < 2)
|
||||
return (NULL);
|
||||
sv->serv.s_port = ((u_short *)key->data)[1];
|
||||
n = strlen(p) + 1;
|
||||
if ((size_t)n > sizeof(sv->line)) {
|
||||
n = sizeof(sv->line);
|
||||
}
|
||||
memcpy(sv->line, p, n);
|
||||
sv->serv.s_name = sv->line;
|
||||
if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL)
|
||||
*(sv->serv.s_proto)++ = '\0';
|
||||
p += n;
|
||||
data->size -= n;
|
||||
} else {
|
||||
if (data->size < sizeof(u_short) + 1)
|
||||
return (NULL);
|
||||
if (key->size > sizeof(sv->line))
|
||||
key->size = sizeof(sv->line);
|
||||
((char *)key->data)[key->size - 1] = '\0';
|
||||
memcpy(sv->line, key->data, key->size);
|
||||
sv->serv.s_name = sv->line;
|
||||
if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL)
|
||||
*(sv->serv.s_proto)++ = '\0';
|
||||
sv->serv.s_port = *(u_short *)data->data;
|
||||
p += sizeof(u_short);
|
||||
data->size -= sizeof(u_short);
|
||||
}
|
||||
q = sv->serv.s_aliases = sv->serv_aliases;
|
||||
while (data->size > 0 && q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) {
|
||||
|
||||
*q++ = p;
|
||||
n = strlen(p) + 1;
|
||||
data->size -= n;
|
||||
p += n;
|
||||
}
|
||||
*q = NULL;
|
||||
return (&sv->serv);
|
||||
}
|
||||
#endif
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Imports */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#ifdef WANT_IRS_NIS
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpcsvc/yp_prot.h>
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef T_NULL
|
||||
#undef T_NULL /* Silence re-definition warning of T_NULL. */
|
||||
#endif
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "hesiod.h"
|
||||
#include "nis_p.h"
|
||||
|
||||
/* Forward */
|
||||
|
||||
static void nis_close(struct irs_acc *);
|
||||
static struct __res_state * nis_res_get(struct irs_acc *);
|
||||
static void nis_res_set(struct irs_acc *, struct __res_state *,
|
||||
void (*)(void *));
|
||||
|
||||
/* Public */
|
||||
|
||||
struct irs_acc *
|
||||
irs_nis_acc(const char *options) {
|
||||
struct nis_p *nis;
|
||||
struct irs_acc *acc;
|
||||
char *domain;
|
||||
|
||||
UNUSED(options);
|
||||
|
||||
if (yp_get_default_domain(&domain) != 0)
|
||||
return (NULL);
|
||||
if (!(nis = memget(sizeof *nis))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(nis, 0, sizeof *nis);
|
||||
if (!(acc = memget(sizeof *acc))) {
|
||||
memput(nis, sizeof *nis);
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(acc, 0x5e, sizeof *acc);
|
||||
acc->private = nis;
|
||||
nis->domain = strdup(domain);
|
||||
#ifdef WANT_IRS_GR
|
||||
acc->gr_map = irs_nis_gr;
|
||||
#else
|
||||
acc->gr_map = NULL;
|
||||
#endif
|
||||
#ifdef WANT_IRS_PW
|
||||
acc->pw_map = irs_nis_pw;
|
||||
#else
|
||||
acc->pw_map = NULL;
|
||||
#endif
|
||||
acc->sv_map = irs_nis_sv;
|
||||
acc->pr_map = irs_nis_pr;
|
||||
acc->ho_map = irs_nis_ho;
|
||||
acc->nw_map = irs_nis_nw;
|
||||
acc->ng_map = irs_nis_ng;
|
||||
acc->res_get = nis_res_get;
|
||||
acc->res_set = nis_res_set;
|
||||
acc->close = nis_close;
|
||||
return (acc);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
static struct __res_state *
|
||||
nis_res_get(struct irs_acc *this) {
|
||||
struct nis_p *nis = (struct nis_p *)this->private;
|
||||
|
||||
if (nis->res == NULL) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)malloc(sizeof *res);
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
memset(res, 0, sizeof *res);
|
||||
nis_res_set(this, res, free);
|
||||
}
|
||||
|
||||
if ((nis->res->options & RES_INIT) == 0 &&
|
||||
res_ninit(nis->res) < 0)
|
||||
return (NULL);
|
||||
|
||||
return (nis->res);
|
||||
}
|
||||
|
||||
static void
|
||||
nis_res_set(struct irs_acc *this, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct nis_p *nis = (struct nis_p *)this->private;
|
||||
|
||||
if (nis->res && nis->free_res) {
|
||||
res_nclose(nis->res);
|
||||
(*nis->free_res)(nis->res);
|
||||
}
|
||||
|
||||
nis->res = res;
|
||||
nis->free_res = free_res;
|
||||
}
|
||||
|
||||
static void
|
||||
nis_close(struct irs_acc *this) {
|
||||
struct nis_p *nis = (struct nis_p *)this->private;
|
||||
|
||||
if (nis->res && nis->free_res)
|
||||
(*nis->free_res)(nis->res);
|
||||
free(nis->domain);
|
||||
memput(nis, sizeof *nis);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
#endif /*WANT_IRS_NIS*/
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* nis_p.h - private include file for the NIS functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Object state.
|
||||
*/
|
||||
struct nis_p {
|
||||
char * domain;
|
||||
struct __res_state * res;
|
||||
void (*free_res) __P((void *));
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Methods.
|
||||
*/
|
||||
|
||||
extern struct irs_gr * irs_nis_gr __P((struct irs_acc *));
|
||||
extern struct irs_pw * irs_nis_pw __P((struct irs_acc *));
|
||||
extern struct irs_sv * irs_nis_sv __P((struct irs_acc *));
|
||||
extern struct irs_pr * irs_nis_pr __P((struct irs_acc *));
|
||||
extern struct irs_ho * irs_nis_ho __P((struct irs_acc *));
|
||||
extern struct irs_nw * irs_nis_nw __P((struct irs_acc *));
|
||||
extern struct irs_ng * irs_nis_ng __P((struct irs_acc *));
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* nul_ng.c - the netgroup accessor null map
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <irs.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
#include "hesiod.h"
|
||||
#include "dns_p.h"
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void ng_close(struct irs_ng *);
|
||||
static int ng_next(struct irs_ng *, const char **,
|
||||
const char **, const char **);
|
||||
static int ng_test(struct irs_ng *,
|
||||
const char *, const char *,
|
||||
const char *, const char *);
|
||||
static void ng_rewind(struct irs_ng *, const char *);
|
||||
static void ng_minimize(struct irs_ng *);
|
||||
|
||||
/* Public. */
|
||||
|
||||
struct irs_ng *
|
||||
irs_nul_ng(struct irs_acc *this) {
|
||||
struct irs_ng *ng;
|
||||
|
||||
UNUSED(this);
|
||||
|
||||
if (!(ng = memget(sizeof *ng))) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
memset(ng, 0x5e, sizeof *ng);
|
||||
ng->private = NULL;
|
||||
ng->close = ng_close;
|
||||
ng->next = ng_next;
|
||||
ng->test = ng_test;
|
||||
ng->rewind = ng_rewind;
|
||||
ng->minimize = ng_minimize;
|
||||
return (ng);
|
||||
}
|
||||
|
||||
/* Methods. */
|
||||
|
||||
static void
|
||||
ng_close(struct irs_ng *this) {
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
ng_next(struct irs_ng *this, const char **host, const char **user,
|
||||
const char **domain)
|
||||
{
|
||||
UNUSED(this);
|
||||
UNUSED(host);
|
||||
UNUSED(user);
|
||||
UNUSED(domain);
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
ng_test(struct irs_ng *this, const char *name,
|
||||
const char *user, const char *host, const char *domain)
|
||||
{
|
||||
UNUSED(this);
|
||||
UNUSED(name);
|
||||
UNUSED(user);
|
||||
UNUSED(host);
|
||||
UNUSED(domain);
|
||||
errno = ENODEV;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static void
|
||||
ng_rewind(struct irs_ng *this, const char *netgroup) {
|
||||
UNUSED(this);
|
||||
UNUSED(netgroup);
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
static void
|
||||
ng_minimize(struct irs_ng *this) {
|
||||
UNUSED(this);
|
||||
/* NOOP */
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _PATH_IRS_CONF
|
||||
#define _PATH_IRS_CONF "/etc/irs.conf"
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_NETWORKS
|
||||
#define _PATH_NETWORKS "/etc/networks"
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_GROUP
|
||||
#define _PATH_GROUP "/etc/group"
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_NETGROUP
|
||||
#define _PATH_NETGROUP "/etc/netgroup"
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_SERVICES
|
||||
#define _PATH_SERVICES "/etc/services"
|
||||
#endif
|
||||
|
||||
#ifdef IRS_LCL_SV_DB
|
||||
#ifndef _PATH_SERVICES_DB
|
||||
#define _PATH_SERVICES_DB _PATH_SERVICES ".db"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _PATH_HESIOD_CONF
|
||||
#define _PATH_HESIOD_CONF "/etc/hesiod.conf"
|
||||
#endif
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <irs.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include "irs_p.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) sprintf x
|
||||
#endif
|
||||
|
||||
void
|
||||
map_v4v6_address(const char *src, char *dst) {
|
||||
u_char *p = (u_char *)dst;
|
||||
char tmp[NS_INADDRSZ];
|
||||
int i;
|
||||
|
||||
/* Stash a temporary copy so our caller can update in place. */
|
||||
memcpy(tmp, src, NS_INADDRSZ);
|
||||
/* Mark this ipv6 addr as a mapped ipv4. */
|
||||
for (i = 0; i < 10; i++)
|
||||
*p++ = 0x00;
|
||||
*p++ = 0xff;
|
||||
*p++ = 0xff;
|
||||
/* Retrieve the saved copy and we're done. */
|
||||
memcpy((void*)p, tmp, NS_INADDRSZ);
|
||||
}
|
||||
|
||||
int
|
||||
make_group_list(struct irs_gr *this, const char *name,
|
||||
gid_t basegid, gid_t *groups, int *ngroups)
|
||||
{
|
||||
struct group *grp;
|
||||
int i, ng;
|
||||
int ret, maxgroups;
|
||||
|
||||
ret = -1;
|
||||
ng = 0;
|
||||
maxgroups = *ngroups;
|
||||
/*
|
||||
* When installing primary group, duplicate it;
|
||||
* the first element of groups is the effective gid
|
||||
* and will be overwritten when a setgid file is executed.
|
||||
*/
|
||||
if (ng >= maxgroups)
|
||||
goto done;
|
||||
groups[ng++] = basegid;
|
||||
if (ng >= maxgroups)
|
||||
goto done;
|
||||
groups[ng++] = basegid;
|
||||
/*
|
||||
* Scan the group file to find additional groups.
|
||||
*/
|
||||
(*this->rewind)(this);
|
||||
while ((grp = (*this->next)(this)) != NULL) {
|
||||
if ((gid_t)grp->gr_gid == basegid)
|
||||
continue;
|
||||
for (i = 0; grp->gr_mem[i]; i++) {
|
||||
if (!strcmp(grp->gr_mem[i], name)) {
|
||||
if (ng >= maxgroups)
|
||||
goto done;
|
||||
groups[ng++] = grp->gr_gid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
done:
|
||||
*ngroups = ng;
|
||||
return (ret);
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1997,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/*
|
||||
* Forward.
|
||||
*/
|
||||
|
||||
static void default_assertion_failed(const char *, int, assertion_type,
|
||||
const char *, int);
|
||||
|
||||
/*
|
||||
* Public.
|
||||
*/
|
||||
|
||||
assertion_failure_callback __assertion_failed = default_assertion_failed;
|
||||
|
||||
void
|
||||
set_assertion_failure_callback(assertion_failure_callback f) {
|
||||
if (f == NULL)
|
||||
__assertion_failed = default_assertion_failed;
|
||||
else
|
||||
__assertion_failed = f;
|
||||
}
|
||||
|
||||
const char *
|
||||
assertion_type_to_text(assertion_type type) {
|
||||
const char *result;
|
||||
|
||||
switch (type) {
|
||||
case assert_require:
|
||||
result = "REQUIRE";
|
||||
break;
|
||||
case assert_ensure:
|
||||
result = "ENSURE";
|
||||
break;
|
||||
case assert_insist:
|
||||
result = "INSIST";
|
||||
break;
|
||||
case assert_invariant:
|
||||
result = "INVARIANT";
|
||||
break;
|
||||
default:
|
||||
result = NULL;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private.
|
||||
*/
|
||||
|
||||
static void
|
||||
default_assertion_failed(const char *file, int line, assertion_type type,
|
||||
const char *cond, int print_errno)
|
||||
{
|
||||
fprintf(stderr, "%s:%d: %s(%s)%s%s failed.\n",
|
||||
file, line, assertion_type_to_text(type), cond,
|
||||
(print_errno) ? ": " : "",
|
||||
(print_errno) ? strerror(errno) : "");
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 1995 by International Business Machines, Inc.
|
||||
*
|
||||
* International Business Machines, Inc. (hereinafter called IBM) grants
|
||||
* permission under its copyrights to use, copy, modify, and distribute this
|
||||
* Software with or without fee, provided that the above copyright notice and
|
||||
* all paragraphs of this notice appear in all copies, and that the name of IBM
|
||||
* not be used in connection with the marketing of any product incorporating
|
||||
* the Software or modifications thereof, without specific, written prior
|
||||
* permission.
|
||||
*
|
||||
* To the extent it has a right to do so, IBM grants an immunity from suit
|
||||
* under its patents, if any, for the use, sale or manufacture of products to
|
||||
* the extent that such products are used for performing Domain Name System
|
||||
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
|
||||
* granted for any product per se or for any other function of any product.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
|
||||
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
|
||||
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#define Assert(Cond) if (!(Cond)) abort()
|
||||
|
||||
static const char Base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char Pad64 = '=';
|
||||
|
||||
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
|
||||
The following encoding technique is taken from RFC 1521 by Borenstein
|
||||
and Freed. It is reproduced here in a slightly edited form for
|
||||
convenience.
|
||||
|
||||
A 65-character subset of US-ASCII is used, enabling 6 bits to be
|
||||
represented per printable character. (The extra 65th character, "=",
|
||||
is used to signify a special processing function.)
|
||||
|
||||
The encoding process represents 24-bit groups of input bits as output
|
||||
strings of 4 encoded characters. Proceeding from left to right, a
|
||||
24-bit input group is formed by concatenating 3 8-bit input groups.
|
||||
These 24 bits are then treated as 4 concatenated 6-bit groups, each
|
||||
of which is translated into a single digit in the base64 alphabet.
|
||||
|
||||
Each 6-bit group is used as an index into an array of 64 printable
|
||||
characters. The character referenced by the index is placed in the
|
||||
output string.
|
||||
|
||||
Table 1: The Base64 Alphabet
|
||||
|
||||
Value Encoding Value Encoding Value Encoding Value Encoding
|
||||
0 A 17 R 34 i 51 z
|
||||
1 B 18 S 35 j 52 0
|
||||
2 C 19 T 36 k 53 1
|
||||
3 D 20 U 37 l 54 2
|
||||
4 E 21 V 38 m 55 3
|
||||
5 F 22 W 39 n 56 4
|
||||
6 G 23 X 40 o 57 5
|
||||
7 H 24 Y 41 p 58 6
|
||||
8 I 25 Z 42 q 59 7
|
||||
9 J 26 a 43 r 60 8
|
||||
10 K 27 b 44 s 61 9
|
||||
11 L 28 c 45 t 62 +
|
||||
12 M 29 d 46 u 63 /
|
||||
13 N 30 e 47 v
|
||||
14 O 31 f 48 w (pad) =
|
||||
15 P 32 g 49 x
|
||||
16 Q 33 h 50 y
|
||||
|
||||
Special processing is performed if fewer than 24 bits are available
|
||||
at the end of the data being encoded. A full encoding quantum is
|
||||
always completed at the end of a quantity. When fewer than 24 input
|
||||
bits are available in an input group, zero bits are added (on the
|
||||
right) to form an integral number of 6-bit groups. Padding at the
|
||||
end of the data is performed using the '=' character.
|
||||
|
||||
Since all base64 input is an integral number of octets, only the
|
||||
-------------------------------------------------
|
||||
following cases can arise:
|
||||
|
||||
(1) the final quantum of encoding input is an integral
|
||||
multiple of 24 bits; here, the final unit of encoded
|
||||
output will be an integral multiple of 4 characters
|
||||
with no "=" padding,
|
||||
(2) the final quantum of encoding input is exactly 8 bits;
|
||||
here, the final unit of encoded output will be two
|
||||
characters followed by two "=" padding characters, or
|
||||
(3) the final quantum of encoding input is exactly 16 bits;
|
||||
here, the final unit of encoded output will be three
|
||||
characters followed by one "=" padding character.
|
||||
*/
|
||||
|
||||
int
|
||||
b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
|
||||
size_t datalength = 0;
|
||||
u_char input[3];
|
||||
u_char output[4];
|
||||
size_t i;
|
||||
|
||||
while (2U < srclength) {
|
||||
input[0] = *src++;
|
||||
input[1] = *src++;
|
||||
input[2] = *src++;
|
||||
srclength -= 3;
|
||||
|
||||
output[0] = input[0] >> 2;
|
||||
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
|
||||
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
|
||||
output[3] = input[2] & 0x3f;
|
||||
Assert(output[0] < 64);
|
||||
Assert(output[1] < 64);
|
||||
Assert(output[2] < 64);
|
||||
Assert(output[3] < 64);
|
||||
|
||||
if (datalength + 4 > targsize)
|
||||
return (-1);
|
||||
target[datalength++] = Base64[output[0]];
|
||||
target[datalength++] = Base64[output[1]];
|
||||
target[datalength++] = Base64[output[2]];
|
||||
target[datalength++] = Base64[output[3]];
|
||||
}
|
||||
|
||||
/* Now we worry about padding. */
|
||||
if (0U != srclength) {
|
||||
/* Get what's left. */
|
||||
input[0] = input[1] = input[2] = '\0';
|
||||
for (i = 0; i < srclength; i++)
|
||||
input[i] = *src++;
|
||||
|
||||
output[0] = input[0] >> 2;
|
||||
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
|
||||
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
|
||||
Assert(output[0] < 64);
|
||||
Assert(output[1] < 64);
|
||||
Assert(output[2] < 64);
|
||||
|
||||
if (datalength + 4 > targsize)
|
||||
return (-1);
|
||||
target[datalength++] = Base64[output[0]];
|
||||
target[datalength++] = Base64[output[1]];
|
||||
if (srclength == 1U)
|
||||
target[datalength++] = Pad64;
|
||||
else
|
||||
target[datalength++] = Base64[output[2]];
|
||||
target[datalength++] = Pad64;
|
||||
}
|
||||
if (datalength >= targsize)
|
||||
return (-1);
|
||||
target[datalength] = '\0'; /* Returned value doesn't count \0. */
|
||||
return (datalength);
|
||||
}
|
||||
|
||||
/* skips all whitespace anywhere.
|
||||
converts characters, four at a time, starting at (or after)
|
||||
src from base - 64 numbers into three 8 bit bytes in the target area.
|
||||
it returns the number of data bytes stored at the target, or -1 on error.
|
||||
*/
|
||||
|
||||
int
|
||||
b64_pton(src, target, targsize)
|
||||
char const *src;
|
||||
u_char *target;
|
||||
size_t targsize;
|
||||
{
|
||||
int tarindex, state, ch;
|
||||
char *pos;
|
||||
|
||||
state = 0;
|
||||
tarindex = 0;
|
||||
|
||||
while ((ch = *src++) != '\0') {
|
||||
if (isspace(ch)) /* Skip whitespace anywhere. */
|
||||
continue;
|
||||
|
||||
if (ch == Pad64)
|
||||
break;
|
||||
|
||||
pos = strchr(Base64, ch);
|
||||
if (pos == 0) /* A non-base64 character. */
|
||||
return (-1);
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (target) {
|
||||
if ((size_t)tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] = (pos - Base64) << 2;
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (target) {
|
||||
if ((size_t)tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 4;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x0f)
|
||||
<< 4 ;
|
||||
}
|
||||
tarindex++;
|
||||
state = 2;
|
||||
break;
|
||||
case 2:
|
||||
if (target) {
|
||||
if ((size_t)tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 2;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x03)
|
||||
<< 6;
|
||||
}
|
||||
tarindex++;
|
||||
state = 3;
|
||||
break;
|
||||
case 3:
|
||||
if (target) {
|
||||
if ((size_t)tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64);
|
||||
}
|
||||
tarindex++;
|
||||
state = 0;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We are done decoding Base-64 chars. Let's see if we ended
|
||||
* on a byte boundary, and/or with erroneous trailing characters.
|
||||
*/
|
||||
|
||||
if (ch == Pad64) { /* We got a pad char. */
|
||||
ch = *src++; /* Skip it, get next. */
|
||||
switch (state) {
|
||||
case 0: /* Invalid = in first position */
|
||||
case 1: /* Invalid = in second position */
|
||||
return (-1);
|
||||
|
||||
case 2: /* Valid, means one byte of info */
|
||||
/* Skip any number of spaces. */
|
||||
for ((void)NULL; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
break;
|
||||
/* Make sure there is another trailing = sign. */
|
||||
if (ch != Pad64)
|
||||
return (-1);
|
||||
ch = *src++; /* Skip the = */
|
||||
/* Fall through to "single trailing =" case. */
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 3: /* Valid, means two bytes of info */
|
||||
/*
|
||||
* We know this char is an =. Is there anything but
|
||||
* whitespace after it?
|
||||
*/
|
||||
for ((void)NULL; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Now make sure for cases 2 and 3 that the "extra"
|
||||
* bits that slopped past the last full byte were
|
||||
* zeros. If we don't check them, they become a
|
||||
* subliminal channel.
|
||||
*/
|
||||
if (target && target[tarindex] != 0)
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We ended by seeing the end of the string. Make sure we
|
||||
* have no partial bytes lying around.
|
||||
*/
|
||||
if (state != 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (tarindex);
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include <isc/misc.h>
|
||||
|
||||
/*
|
||||
* int
|
||||
* bitncmp(l, r, n)
|
||||
* compare bit masks l and r, for n bits.
|
||||
* return:
|
||||
* -1, 1, or 0 in the libc tradition.
|
||||
* note:
|
||||
* network byte order assumed. this means 192.5.5.240/28 has
|
||||
* 0x11110000 in its fourth octet.
|
||||
* author:
|
||||
* Paul Vixie (ISC), June 1996
|
||||
*/
|
||||
int
|
||||
bitncmp(const void *l, const void *r, int n) {
|
||||
u_int lb, rb;
|
||||
int x, b;
|
||||
|
||||
b = n / 8;
|
||||
x = memcmp(l, r, b);
|
||||
if (x)
|
||||
return (x);
|
||||
|
||||
lb = ((const u_char *)l)[b];
|
||||
rb = ((const u_char *)r)[b];
|
||||
for (b = n % 8; b > 0; b--) {
|
||||
if ((lb & 0x80) != (rb & 0x80)) {
|
||||
if (lb & 0x80)
|
||||
return (1);
|
||||
return (-1);
|
||||
}
|
||||
lb <<= 1;
|
||||
rb <<= 1;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -1,602 +0,0 @@
|
||||
#if !defined(lint) && !defined(SABER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Extern. */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <isc/ctl.h>
|
||||
#include <isc/eventlib.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "ctl_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Constants. */
|
||||
|
||||
|
||||
/* Macros. */
|
||||
|
||||
#define donefunc_p(ctx) ((ctx).donefunc != NULL)
|
||||
#define arpacode_p(line) (isdigit((unsigned char)(line[0])) && \
|
||||
isdigit((unsigned char)(line[1])) && \
|
||||
isdigit((unsigned char)(line[2])))
|
||||
#define arpacont_p(line) (line[3] == '-')
|
||||
#define arpadone_p(line) (line[3] == ' ' || line[3] == '\t' || \
|
||||
line[3] == '\r' || line[3] == '\0')
|
||||
|
||||
/* Types. */
|
||||
|
||||
enum state {
|
||||
initializing = 0, connecting, connected, destroyed
|
||||
};
|
||||
|
||||
struct ctl_tran {
|
||||
LINK(struct ctl_tran) link;
|
||||
LINK(struct ctl_tran) wlink;
|
||||
struct ctl_cctx * ctx;
|
||||
struct ctl_buf outbuf;
|
||||
ctl_clntdone donefunc;
|
||||
void * uap;
|
||||
};
|
||||
|
||||
struct ctl_cctx {
|
||||
enum state state;
|
||||
evContext ev;
|
||||
int sock;
|
||||
ctl_logfunc logger;
|
||||
ctl_clntdone donefunc;
|
||||
void * uap;
|
||||
evConnID coID;
|
||||
evTimerID tiID;
|
||||
evFileID rdID;
|
||||
evStreamID wrID;
|
||||
struct ctl_buf inbuf;
|
||||
struct timespec timeout;
|
||||
LIST(struct ctl_tran) tran;
|
||||
LIST(struct ctl_tran) wtran;
|
||||
};
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static struct ctl_tran *new_tran(struct ctl_cctx *, ctl_clntdone, void *, int);
|
||||
static void start_write(struct ctl_cctx *);
|
||||
static void destroy(struct ctl_cctx *, int);
|
||||
static void error(struct ctl_cctx *);
|
||||
static void new_state(struct ctl_cctx *, enum state);
|
||||
static void conn_done(evContext, void *, int,
|
||||
const void *, int,
|
||||
const void *, int);
|
||||
static void write_done(evContext, void *, int, int);
|
||||
static void start_read(struct ctl_cctx *);
|
||||
static void stop_read(struct ctl_cctx *);
|
||||
static void readable(evContext, void *, int, int);
|
||||
static void start_timer(struct ctl_cctx *);
|
||||
static void stop_timer(struct ctl_cctx *);
|
||||
static void touch_timer(struct ctl_cctx *);
|
||||
static void timer(evContext, void *,
|
||||
struct timespec, struct timespec);
|
||||
|
||||
/* Private data. */
|
||||
|
||||
static const char * const state_names[] = {
|
||||
"initializing", "connecting", "connected", "destroyed"
|
||||
};
|
||||
|
||||
/* Public. */
|
||||
|
||||
/*
|
||||
* void
|
||||
* ctl_client()
|
||||
* create, condition, and connect to a listener on the control port.
|
||||
*/
|
||||
struct ctl_cctx *
|
||||
ctl_client(evContext lev, const struct sockaddr *cap, size_t cap_len,
|
||||
const struct sockaddr *sap, size_t sap_len,
|
||||
ctl_clntdone donefunc, void *uap,
|
||||
u_int timeout, ctl_logfunc logger)
|
||||
{
|
||||
static const char me[] = "ctl_client";
|
||||
static const int on = 1;
|
||||
struct ctl_cctx *ctx;
|
||||
struct sockaddr *captmp;
|
||||
|
||||
if (logger == NULL)
|
||||
logger = ctl_logger;
|
||||
ctx = memget(sizeof *ctx);
|
||||
if (ctx == NULL) {
|
||||
(*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno));
|
||||
goto fatal;
|
||||
}
|
||||
ctx->state = initializing;
|
||||
ctx->ev = lev;
|
||||
ctx->logger = logger;
|
||||
ctx->timeout = evConsTime(timeout, 0);
|
||||
ctx->donefunc = donefunc;
|
||||
ctx->uap = uap;
|
||||
ctx->coID.opaque = NULL;
|
||||
ctx->tiID.opaque = NULL;
|
||||
ctx->rdID.opaque = NULL;
|
||||
ctx->wrID.opaque = NULL;
|
||||
buffer_init(ctx->inbuf);
|
||||
INIT_LIST(ctx->tran);
|
||||
INIT_LIST(ctx->wtran);
|
||||
ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC);
|
||||
if (ctx->sock > evHighestFD(ctx->ev)) {
|
||||
ctx->sock = -1;
|
||||
errno = ENOTSOCK;
|
||||
}
|
||||
if (ctx->sock < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: socket: %s",
|
||||
me, strerror(errno));
|
||||
goto fatal;
|
||||
}
|
||||
if (cap != NULL) {
|
||||
if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char *)&on, sizeof on) != 0) {
|
||||
(*ctx->logger)(ctl_warning,
|
||||
"%s: setsockopt(REUSEADDR): %s",
|
||||
me, strerror(errno));
|
||||
}
|
||||
DE_CONST(cap, captmp);
|
||||
if (bind(ctx->sock, captmp, cap_len) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: bind: %s", me,
|
||||
strerror(errno));
|
||||
goto fatal;
|
||||
}
|
||||
}
|
||||
if (evConnect(lev, ctx->sock, (const struct sockaddr *)sap, sap_len,
|
||||
conn_done, ctx, &ctx->coID) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: evConnect(fd %d): %s",
|
||||
me, ctx->sock, strerror(errno));
|
||||
fatal:
|
||||
if (ctx != NULL) {
|
||||
if (ctx->sock >= 0)
|
||||
close(ctx->sock);
|
||||
memput(ctx, sizeof *ctx);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
new_state(ctx, connecting);
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* void
|
||||
* ctl_endclient(ctx)
|
||||
* close a client and release all of its resources.
|
||||
*/
|
||||
void
|
||||
ctl_endclient(struct ctl_cctx *ctx) {
|
||||
if (ctx->state != destroyed)
|
||||
destroy(ctx, 0);
|
||||
memput(ctx, sizeof *ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* int
|
||||
* ctl_command(ctx, cmd, len, donefunc, uap)
|
||||
* Queue a transaction, which will begin with sending cmd
|
||||
* and complete by calling donefunc with the answer.
|
||||
*/
|
||||
int
|
||||
ctl_command(struct ctl_cctx *ctx, const char *cmd, size_t len,
|
||||
ctl_clntdone donefunc, void *uap)
|
||||
{
|
||||
struct ctl_tran *tran;
|
||||
char *pc;
|
||||
unsigned int n;
|
||||
|
||||
switch (ctx->state) {
|
||||
case destroyed:
|
||||
errno = ENOTCONN;
|
||||
return (-1);
|
||||
case connecting:
|
||||
case connected:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (len >= (size_t)MAX_LINELEN) {
|
||||
errno = EMSGSIZE;
|
||||
return (-1);
|
||||
}
|
||||
tran = new_tran(ctx, donefunc, uap, 1);
|
||||
if (tran == NULL)
|
||||
return (-1);
|
||||
if (ctl_bufget(&tran->outbuf, ctx->logger) < 0)
|
||||
return (-1);
|
||||
memcpy(tran->outbuf.text, cmd, len);
|
||||
tran->outbuf.used = len;
|
||||
for (pc = tran->outbuf.text, n = 0; n < tran->outbuf.used; pc++, n++)
|
||||
if (!isascii((unsigned char)*pc) ||
|
||||
!isprint((unsigned char)*pc))
|
||||
*pc = '\040';
|
||||
start_write(ctx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
static struct ctl_tran *
|
||||
new_tran(struct ctl_cctx *ctx, ctl_clntdone donefunc, void *uap, int w) {
|
||||
struct ctl_tran *new = memget(sizeof *new);
|
||||
|
||||
if (new == NULL)
|
||||
return (NULL);
|
||||
new->ctx = ctx;
|
||||
buffer_init(new->outbuf);
|
||||
new->donefunc = donefunc;
|
||||
new->uap = uap;
|
||||
INIT_LINK(new, link);
|
||||
INIT_LINK(new, wlink);
|
||||
APPEND(ctx->tran, new, link);
|
||||
if (w)
|
||||
APPEND(ctx->wtran, new, wlink);
|
||||
return (new);
|
||||
}
|
||||
|
||||
static void
|
||||
start_write(struct ctl_cctx *ctx) {
|
||||
static const char me[] = "isc/ctl_clnt::start_write";
|
||||
struct ctl_tran *tran;
|
||||
struct iovec iov[2], *iovp = iov;
|
||||
char * tmp;
|
||||
|
||||
REQUIRE(ctx->state == connecting || ctx->state == connected);
|
||||
/* If there is a write in progress, don't try to write more yet. */
|
||||
if (ctx->wrID.opaque != NULL)
|
||||
return;
|
||||
/* If there are no trans, make sure timer is off, and we're done. */
|
||||
if (EMPTY(ctx->wtran)) {
|
||||
if (ctx->tiID.opaque != NULL)
|
||||
stop_timer(ctx);
|
||||
return;
|
||||
}
|
||||
/* Pull it off the head of the write queue. */
|
||||
tran = HEAD(ctx->wtran);
|
||||
UNLINK(ctx->wtran, tran, wlink);
|
||||
/* Since there are some trans, make sure timer is successfully "on". */
|
||||
if (ctx->tiID.opaque != NULL)
|
||||
touch_timer(ctx);
|
||||
else
|
||||
start_timer(ctx);
|
||||
if (ctx->state == destroyed)
|
||||
return;
|
||||
/* Marshall a newline-terminated message and clock it out. */
|
||||
*iovp++ = evConsIovec(tran->outbuf.text, tran->outbuf.used);
|
||||
DE_CONST("\r\n", tmp);
|
||||
*iovp++ = evConsIovec(tmp, 2);
|
||||
if (evWrite(ctx->ev, ctx->sock, iov, iovp - iov,
|
||||
write_done, tran, &ctx->wrID) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: evWrite: %s", me,
|
||||
strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
if (evTimeRW(ctx->ev, ctx->wrID, ctx->tiID) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: evTimeRW: %s", me,
|
||||
strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy(struct ctl_cctx *ctx, int notify) {
|
||||
struct ctl_tran *this, *next;
|
||||
|
||||
if (ctx->sock != -1) {
|
||||
(void) close(ctx->sock);
|
||||
ctx->sock = -1;
|
||||
}
|
||||
switch (ctx->state) {
|
||||
case connecting:
|
||||
REQUIRE(ctx->wrID.opaque == NULL);
|
||||
REQUIRE(EMPTY(ctx->tran));
|
||||
/*
|
||||
* This test is nec'y since destroy() can be called from
|
||||
* start_read() while the state is still "connecting".
|
||||
*/
|
||||
if (ctx->coID.opaque != NULL) {
|
||||
(void)evCancelConn(ctx->ev, ctx->coID);
|
||||
ctx->coID.opaque = NULL;
|
||||
}
|
||||
break;
|
||||
case connected:
|
||||
REQUIRE(ctx->coID.opaque == NULL);
|
||||
if (ctx->wrID.opaque != NULL) {
|
||||
(void)evCancelRW(ctx->ev, ctx->wrID);
|
||||
ctx->wrID.opaque = NULL;
|
||||
}
|
||||
if (ctx->rdID.opaque != NULL)
|
||||
stop_read(ctx);
|
||||
break;
|
||||
case destroyed:
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (allocated_p(ctx->inbuf))
|
||||
ctl_bufput(&ctx->inbuf);
|
||||
for (this = HEAD(ctx->tran); this != NULL; this = next) {
|
||||
next = NEXT(this, link);
|
||||
if (allocated_p(this->outbuf))
|
||||
ctl_bufput(&this->outbuf);
|
||||
if (notify && this->donefunc != NULL)
|
||||
(*this->donefunc)(ctx, this->uap, NULL, 0);
|
||||
memput(this, sizeof *this);
|
||||
}
|
||||
if (ctx->tiID.opaque != NULL)
|
||||
stop_timer(ctx);
|
||||
new_state(ctx, destroyed);
|
||||
}
|
||||
|
||||
static void
|
||||
error(struct ctl_cctx *ctx) {
|
||||
REQUIRE(ctx->state != destroyed);
|
||||
destroy(ctx, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
new_state(struct ctl_cctx *ctx, enum state new_state) {
|
||||
static const char me[] = "isc/ctl_clnt::new_state";
|
||||
|
||||
(*ctx->logger)(ctl_debug, "%s: %s -> %s", me,
|
||||
state_names[ctx->state], state_names[new_state]);
|
||||
ctx->state = new_state;
|
||||
}
|
||||
|
||||
static void
|
||||
conn_done(evContext ev, void *uap, int fd,
|
||||
const void *la, int lalen,
|
||||
const void *ra, int ralen)
|
||||
{
|
||||
static const char me[] = "isc/ctl_clnt::conn_done";
|
||||
struct ctl_cctx *ctx = uap;
|
||||
struct ctl_tran *tran;
|
||||
|
||||
UNUSED(ev);
|
||||
UNUSED(la);
|
||||
UNUSED(lalen);
|
||||
UNUSED(ra);
|
||||
UNUSED(ralen);
|
||||
|
||||
ctx->coID.opaque = NULL;
|
||||
if (fd < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: evConnect: %s", me,
|
||||
strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
new_state(ctx, connected);
|
||||
tran = new_tran(ctx, ctx->donefunc, ctx->uap, 0);
|
||||
if (tran == NULL) {
|
||||
(*ctx->logger)(ctl_error, "%s: new_tran failed: %s", me,
|
||||
strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
start_read(ctx);
|
||||
if (ctx->state == destroyed) {
|
||||
(*ctx->logger)(ctl_error, "%s: start_read failed: %s",
|
||||
me, strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_done(evContext lev, void *uap, int fd, int bytes) {
|
||||
struct ctl_tran *tran = (struct ctl_tran *)uap;
|
||||
struct ctl_cctx *ctx = tran->ctx;
|
||||
|
||||
UNUSED(lev);
|
||||
UNUSED(fd);
|
||||
|
||||
ctx->wrID.opaque = NULL;
|
||||
if (ctx->tiID.opaque != NULL)
|
||||
touch_timer(ctx);
|
||||
ctl_bufput(&tran->outbuf);
|
||||
start_write(ctx);
|
||||
if (bytes < 0)
|
||||
destroy(ctx, 1);
|
||||
else
|
||||
start_read(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
start_read(struct ctl_cctx *ctx) {
|
||||
static const char me[] = "isc/ctl_clnt::start_read";
|
||||
|
||||
REQUIRE(ctx->state == connecting || ctx->state == connected);
|
||||
REQUIRE(ctx->rdID.opaque == NULL);
|
||||
if (evSelectFD(ctx->ev, ctx->sock, EV_READ, readable, ctx,
|
||||
&ctx->rdID) < 0)
|
||||
{
|
||||
(*ctx->logger)(ctl_error, "%s: evSelect(fd %d): %s", me,
|
||||
ctx->sock, strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_read(struct ctl_cctx *ctx) {
|
||||
REQUIRE(ctx->coID.opaque == NULL);
|
||||
REQUIRE(ctx->rdID.opaque != NULL);
|
||||
(void)evDeselectFD(ctx->ev, ctx->rdID);
|
||||
ctx->rdID.opaque = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
readable(evContext ev, void *uap, int fd, int evmask) {
|
||||
static const char me[] = "isc/ctl_clnt::readable";
|
||||
struct ctl_cctx *ctx = uap;
|
||||
struct ctl_tran *tran;
|
||||
ssize_t n;
|
||||
char *eos;
|
||||
|
||||
UNUSED(ev);
|
||||
|
||||
REQUIRE(ctx != NULL);
|
||||
REQUIRE(fd >= 0);
|
||||
REQUIRE(evmask == EV_READ);
|
||||
REQUIRE(ctx->state == connected);
|
||||
REQUIRE(!EMPTY(ctx->tran));
|
||||
tran = HEAD(ctx->tran);
|
||||
if (!allocated_p(ctx->inbuf) &&
|
||||
ctl_bufget(&ctx->inbuf, ctx->logger) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: can't get an input buffer", me);
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
n = read(ctx->sock, ctx->inbuf.text + ctx->inbuf.used,
|
||||
MAX_LINELEN - ctx->inbuf.used);
|
||||
if (n <= 0) {
|
||||
(*ctx->logger)(ctl_warning, "%s: read: %s", me,
|
||||
(n == 0) ? "Unexpected EOF" : strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
if (ctx->tiID.opaque != NULL)
|
||||
touch_timer(ctx);
|
||||
ctx->inbuf.used += n;
|
||||
(*ctx->logger)(ctl_debug, "%s: read %d, used %d", me,
|
||||
n, ctx->inbuf.used);
|
||||
again:
|
||||
eos = memchr(ctx->inbuf.text, '\n', ctx->inbuf.used);
|
||||
if (eos != NULL && eos != ctx->inbuf.text && eos[-1] == '\r') {
|
||||
int done = 0;
|
||||
|
||||
eos[-1] = '\0';
|
||||
if (!arpacode_p(ctx->inbuf.text)) {
|
||||
/* XXX Doesn't FTP do this sometimes? Is it legal? */
|
||||
(*ctx->logger)(ctl_error, "%s: no arpa code (%s)", me,
|
||||
ctx->inbuf.text);
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
if (arpadone_p(ctx->inbuf.text))
|
||||
done = 1;
|
||||
else if (arpacont_p(ctx->inbuf.text))
|
||||
done = 0;
|
||||
else {
|
||||
/* XXX Doesn't FTP do this sometimes? Is it legal? */
|
||||
(*ctx->logger)(ctl_error, "%s: no arpa flag (%s)", me,
|
||||
ctx->inbuf.text);
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
(*tran->donefunc)(ctx, tran->uap, ctx->inbuf.text,
|
||||
(done ? 0 : CTL_MORE));
|
||||
ctx->inbuf.used -= ((eos - ctx->inbuf.text) + 1);
|
||||
if (ctx->inbuf.used == 0U)
|
||||
ctl_bufput(&ctx->inbuf);
|
||||
else
|
||||
memmove(ctx->inbuf.text, eos + 1, ctx->inbuf.used);
|
||||
if (done) {
|
||||
UNLINK(ctx->tran, tran, link);
|
||||
memput(tran, sizeof *tran);
|
||||
stop_read(ctx);
|
||||
start_write(ctx);
|
||||
return;
|
||||
}
|
||||
if (allocated_p(ctx->inbuf))
|
||||
goto again;
|
||||
return;
|
||||
}
|
||||
if (ctx->inbuf.used == (size_t)MAX_LINELEN) {
|
||||
(*ctx->logger)(ctl_error, "%s: line too long (%-10s...)", me,
|
||||
ctx->inbuf.text);
|
||||
error(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Timer related stuff. */
|
||||
|
||||
static void
|
||||
start_timer(struct ctl_cctx *ctx) {
|
||||
static const char me[] = "isc/ctl_clnt::start_timer";
|
||||
|
||||
REQUIRE(ctx->tiID.opaque == NULL);
|
||||
if (evSetIdleTimer(ctx->ev, timer, ctx, ctx->timeout, &ctx->tiID) < 0){
|
||||
(*ctx->logger)(ctl_error, "%s: evSetIdleTimer: %s", me,
|
||||
strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_timer(struct ctl_cctx *ctx) {
|
||||
static const char me[] = "isc/ctl_clnt::stop_timer";
|
||||
|
||||
REQUIRE(ctx->tiID.opaque != NULL);
|
||||
if (evClearIdleTimer(ctx->ev, ctx->tiID) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: evClearIdleTimer: %s", me,
|
||||
strerror(errno));
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
ctx->tiID.opaque = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
touch_timer(struct ctl_cctx *ctx) {
|
||||
REQUIRE(ctx->tiID.opaque != NULL);
|
||||
|
||||
evTouchIdleTimer(ctx->ev, ctx->tiID);
|
||||
}
|
||||
|
||||
static void
|
||||
timer(evContext ev, void *uap, struct timespec due, struct timespec itv) {
|
||||
static const char me[] = "isc/ctl_clnt::timer";
|
||||
struct ctl_cctx *ctx = uap;
|
||||
|
||||
UNUSED(ev);
|
||||
UNUSED(due);
|
||||
UNUSED(itv);
|
||||
|
||||
ctx->tiID.opaque = NULL;
|
||||
(*ctx->logger)(ctl_error, "%s: timeout after %u seconds while %s", me,
|
||||
ctx->timeout.tv_sec, state_names[ctx->state]);
|
||||
error(ctx);
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
#if !defined(lint) && !defined(SABER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Extern. */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <isc/eventlib.h>
|
||||
#include <isc/logging.h>
|
||||
#include <isc/memcluster.h>
|
||||
#include <isc/ctl.h>
|
||||
|
||||
#include "ctl_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Constants. */
|
||||
|
||||
const char * const ctl_sevnames[] = {
|
||||
"debug", "warning", "error"
|
||||
};
|
||||
|
||||
/* Public. */
|
||||
|
||||
/*
|
||||
* ctl_logger()
|
||||
* if ctl_startup()'s caller didn't specify a logger, this one
|
||||
* is used. this pollutes stderr with all kinds of trash so it will
|
||||
* probably never be used in real applications.
|
||||
*/
|
||||
void
|
||||
ctl_logger(enum ctl_severity severity, const char *format, ...) {
|
||||
va_list ap;
|
||||
static const char me[] = "ctl_logger";
|
||||
|
||||
fprintf(stderr, "%s(%s): ", me, ctl_sevnames[severity]);
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
int
|
||||
ctl_bufget(struct ctl_buf *buf, ctl_logfunc logger) {
|
||||
static const char me[] = "ctl_bufget";
|
||||
|
||||
REQUIRE(!allocated_p(*buf) && buf->used == 0U);
|
||||
buf->text = memget(MAX_LINELEN);
|
||||
if (!allocated_p(*buf)) {
|
||||
(*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
buf->used = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ctl_bufput(struct ctl_buf *buf) {
|
||||
|
||||
REQUIRE(allocated_p(*buf));
|
||||
memput(buf->text, MAX_LINELEN);
|
||||
buf->text = NULL;
|
||||
buf->used = 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
ctl_sa_ntop(const struct sockaddr *sa,
|
||||
char *buf, size_t size,
|
||||
ctl_logfunc logger)
|
||||
{
|
||||
static const char me[] = "ctl_sa_ntop";
|
||||
static const char punt[] = "[0].-1";
|
||||
char tmp[INET6_ADDRSTRLEN];
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET6: {
|
||||
const struct sockaddr_in6 *in6 =
|
||||
(const struct sockaddr_in6 *) sa;
|
||||
|
||||
if (inet_ntop(in6->sin6_family, &in6->sin6_addr, tmp, sizeof tmp)
|
||||
== NULL) {
|
||||
(*logger)(ctl_error, "%s: inet_ntop(%u %04x): %s",
|
||||
me, in6->sin6_family,
|
||||
in6->sin6_port, strerror(errno));
|
||||
return (punt);
|
||||
}
|
||||
if (strlen(tmp) + sizeof "[].65535" > size) {
|
||||
(*logger)(ctl_error, "%s: buffer overflow", me);
|
||||
return (punt);
|
||||
}
|
||||
(void) sprintf(buf, "[%s].%u", tmp, ntohs(in6->sin6_port));
|
||||
return (buf);
|
||||
}
|
||||
case AF_INET: {
|
||||
const struct sockaddr_in *in =
|
||||
(const struct sockaddr_in *) sa;
|
||||
|
||||
if (inet_ntop(in->sin_family, &in->sin_addr, tmp, sizeof tmp)
|
||||
== NULL) {
|
||||
(*logger)(ctl_error, "%s: inet_ntop(%u %04x %08x): %s",
|
||||
me, in->sin_family,
|
||||
in->sin_port, in->sin_addr.s_addr,
|
||||
strerror(errno));
|
||||
return (punt);
|
||||
}
|
||||
if (strlen(tmp) + sizeof "[].65535" > size) {
|
||||
(*logger)(ctl_error, "%s: buffer overflow", me);
|
||||
return (punt);
|
||||
}
|
||||
(void) sprintf(buf, "[%s].%u", tmp, ntohs(in->sin_port));
|
||||
return (buf);
|
||||
}
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
case AF_UNIX: {
|
||||
const struct sockaddr_un *un =
|
||||
(const struct sockaddr_un *) sa;
|
||||
unsigned int x = sizeof un->sun_path;
|
||||
|
||||
if (x > size)
|
||||
x = size;
|
||||
strncpy(buf, un->sun_path, x - 1);
|
||||
buf[x - 1] = '\0';
|
||||
return (buf);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return (punt);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ctl_sa_copy(const struct sockaddr *src, struct sockaddr *dst) {
|
||||
switch (src->sa_family) {
|
||||
case AF_INET6:
|
||||
*((struct sockaddr_in6 *)dst) =
|
||||
*((const struct sockaddr_in6 *)src);
|
||||
break;
|
||||
case AF_INET:
|
||||
*((struct sockaddr_in *)dst) =
|
||||
*((const struct sockaddr_in *)src);
|
||||
break;
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
case AF_UNIX:
|
||||
*((struct sockaddr_un *)dst) =
|
||||
*((const struct sockaddr_un *)src);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
*dst = *src;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
struct ctl_buf {
|
||||
char * text;
|
||||
size_t used;
|
||||
};
|
||||
|
||||
#define MAX_LINELEN 990 /* Like SMTP. */
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
#define MAX_NTOP PATH_MAX
|
||||
#else
|
||||
#define MAX_NTOP (sizeof "[255.255.255.255].65535")
|
||||
#endif
|
||||
|
||||
#define allocated_p(Buf) ((Buf).text != NULL)
|
||||
#define buffer_init(Buf) ((Buf).text = 0, (Buf.used) = 0)
|
||||
|
||||
#define ctl_bufget __ctl_bufget
|
||||
#define ctl_bufput __ctl_bufput
|
||||
#define ctl_sa_ntop __ctl_sa_ntop
|
||||
#define ctl_sa_copy __ctl_sa_copy
|
||||
|
||||
int ctl_bufget(struct ctl_buf *, ctl_logfunc);
|
||||
void ctl_bufput(struct ctl_buf *);
|
||||
const char * ctl_sa_ntop(const struct sockaddr *, char *, size_t,
|
||||
ctl_logfunc);
|
||||
void ctl_sa_copy(const struct sockaddr *,
|
||||
struct sockaddr *);
|
||||
@@ -1,780 +0,0 @@
|
||||
#if !defined(lint) && !defined(SABER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1998,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Extern. */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <isc/ctl.h>
|
||||
#include <isc/eventlib.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/logging.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#include "ctl_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
#else
|
||||
# define SPRINTF(x) ((size_t)sprintf x)
|
||||
#endif
|
||||
|
||||
/* Macros. */
|
||||
|
||||
#define lastverb_p(verb) (verb->name == NULL || verb->func == NULL)
|
||||
#define address_expr ctl_sa_ntop((struct sockaddr *)&sess->sa, \
|
||||
tmp, sizeof tmp, ctx->logger)
|
||||
|
||||
/* Types. */
|
||||
|
||||
enum state {
|
||||
available = 0, initializing, writing, reading, reading_data,
|
||||
processing, idling, quitting, closing
|
||||
};
|
||||
|
||||
union sa_un {
|
||||
struct sockaddr_in in;
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
struct sockaddr_un un;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ctl_sess {
|
||||
LINK(struct ctl_sess) link;
|
||||
struct ctl_sctx * ctx;
|
||||
enum state state;
|
||||
int sock;
|
||||
union sa_un sa;
|
||||
evFileID rdID;
|
||||
evStreamID wrID;
|
||||
evTimerID rdtiID;
|
||||
evTimerID wrtiID;
|
||||
struct ctl_buf inbuf;
|
||||
struct ctl_buf outbuf;
|
||||
const struct ctl_verb * verb;
|
||||
u_int helpcode;
|
||||
const void * respctx;
|
||||
u_int respflags;
|
||||
ctl_srvrdone donefunc;
|
||||
void * uap;
|
||||
void * csctx;
|
||||
};
|
||||
|
||||
struct ctl_sctx {
|
||||
evContext ev;
|
||||
void * uctx;
|
||||
u_int unkncode;
|
||||
u_int timeoutcode;
|
||||
const struct ctl_verb * verbs;
|
||||
const struct ctl_verb * connverb;
|
||||
int sock;
|
||||
int max_sess;
|
||||
int cur_sess;
|
||||
struct timespec timeout;
|
||||
ctl_logfunc logger;
|
||||
evConnID acID;
|
||||
LIST(struct ctl_sess) sess;
|
||||
};
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void ctl_accept(evContext, void *, int,
|
||||
const void *, int,
|
||||
const void *, int);
|
||||
static void ctl_close(struct ctl_sess *);
|
||||
static void ctl_new_state(struct ctl_sess *,
|
||||
enum state,
|
||||
const char *);
|
||||
static void ctl_start_read(struct ctl_sess *);
|
||||
static void ctl_stop_read(struct ctl_sess *);
|
||||
static void ctl_readable(evContext, void *, int, int);
|
||||
static void ctl_rdtimeout(evContext, void *,
|
||||
struct timespec,
|
||||
struct timespec);
|
||||
static void ctl_wrtimeout(evContext, void *,
|
||||
struct timespec,
|
||||
struct timespec);
|
||||
static void ctl_docommand(struct ctl_sess *);
|
||||
static void ctl_writedone(evContext, void *, int, int);
|
||||
static void ctl_morehelp(struct ctl_sctx *,
|
||||
struct ctl_sess *,
|
||||
const struct ctl_verb *,
|
||||
const char *,
|
||||
u_int, const void *, void *);
|
||||
static void ctl_signal_done(struct ctl_sctx *,
|
||||
struct ctl_sess *);
|
||||
|
||||
/* Private data. */
|
||||
|
||||
static const char * state_names[] = {
|
||||
"available", "initializing", "writing", "reading",
|
||||
"reading_data", "processing", "idling", "quitting", "closing"
|
||||
};
|
||||
|
||||
static const char space[] = " ";
|
||||
|
||||
static const struct ctl_verb fakehelpverb = {
|
||||
"fakehelp", ctl_morehelp , NULL
|
||||
};
|
||||
|
||||
/* Public. */
|
||||
|
||||
/*
|
||||
* void
|
||||
* ctl_server()
|
||||
* create, condition, and start a listener on the control port.
|
||||
*/
|
||||
struct ctl_sctx *
|
||||
ctl_server(evContext lev, const struct sockaddr *sap, size_t sap_len,
|
||||
const struct ctl_verb *verbs,
|
||||
u_int unkncode, u_int timeoutcode,
|
||||
u_int timeout, int backlog, int max_sess,
|
||||
ctl_logfunc logger, void *uctx)
|
||||
{
|
||||
static const char me[] = "ctl_server";
|
||||
static const int on = 1;
|
||||
const struct ctl_verb *connverb;
|
||||
struct ctl_sctx *ctx;
|
||||
int save_errno;
|
||||
|
||||
if (logger == NULL)
|
||||
logger = ctl_logger;
|
||||
for (connverb = verbs;
|
||||
connverb->name != NULL && connverb->func != NULL;
|
||||
connverb++)
|
||||
if (connverb->name[0] == '\0')
|
||||
break;
|
||||
if (connverb->func == NULL) {
|
||||
(*logger)(ctl_error, "%s: no connection verb found", me);
|
||||
return (NULL);
|
||||
}
|
||||
ctx = memget(sizeof *ctx);
|
||||
if (ctx == NULL) {
|
||||
(*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
ctx->ev = lev;
|
||||
ctx->uctx = uctx;
|
||||
ctx->unkncode = unkncode;
|
||||
ctx->timeoutcode = timeoutcode;
|
||||
ctx->verbs = verbs;
|
||||
ctx->timeout = evConsTime(timeout, 0);
|
||||
ctx->logger = logger;
|
||||
ctx->connverb = connverb;
|
||||
ctx->max_sess = max_sess;
|
||||
ctx->cur_sess = 0;
|
||||
INIT_LIST(ctx->sess);
|
||||
ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC);
|
||||
if (ctx->sock > evHighestFD(ctx->ev)) {
|
||||
ctx->sock = -1;
|
||||
errno = ENOTSOCK;
|
||||
}
|
||||
if (ctx->sock < 0) {
|
||||
save_errno = errno;
|
||||
(*ctx->logger)(ctl_error, "%s: socket: %s",
|
||||
me, strerror(errno));
|
||||
memput(ctx, sizeof *ctx);
|
||||
errno = save_errno;
|
||||
return (NULL);
|
||||
}
|
||||
if (ctx->sock > evHighestFD(lev)) {
|
||||
close(ctx->sock);
|
||||
(*ctx->logger)(ctl_error, "%s: file descriptor > evHighestFD");
|
||||
errno = ENFILE;
|
||||
memput(ctx, sizeof *ctx);
|
||||
return (NULL);
|
||||
}
|
||||
#ifdef NO_UNIX_REUSEADDR
|
||||
if (sap->sa_family != AF_UNIX)
|
||||
#endif
|
||||
if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char *)&on, sizeof on) != 0) {
|
||||
(*ctx->logger)(ctl_warning,
|
||||
"%s: setsockopt(REUSEADDR): %s",
|
||||
me, strerror(errno));
|
||||
}
|
||||
if (bind(ctx->sock, sap, sap_len) < 0) {
|
||||
char tmp[MAX_NTOP];
|
||||
save_errno = errno;
|
||||
(*ctx->logger)(ctl_error, "%s: bind: %s: %s",
|
||||
me, ctl_sa_ntop((const struct sockaddr *)sap,
|
||||
tmp, sizeof tmp, ctx->logger),
|
||||
strerror(save_errno));
|
||||
close(ctx->sock);
|
||||
memput(ctx, sizeof *ctx);
|
||||
errno = save_errno;
|
||||
return (NULL);
|
||||
}
|
||||
if (fcntl(ctx->sock, F_SETFD, 1) < 0) {
|
||||
(*ctx->logger)(ctl_warning, "%s: fcntl: %s", me,
|
||||
strerror(errno));
|
||||
}
|
||||
if (evListen(lev, ctx->sock, backlog, ctl_accept, ctx,
|
||||
&ctx->acID) < 0) {
|
||||
save_errno = errno;
|
||||
(*ctx->logger)(ctl_error, "%s: evListen(fd %d): %s",
|
||||
me, ctx->sock, strerror(errno));
|
||||
close(ctx->sock);
|
||||
memput(ctx, sizeof *ctx);
|
||||
errno = save_errno;
|
||||
return (NULL);
|
||||
}
|
||||
(*ctx->logger)(ctl_debug, "%s: new ctx %p, sock %d",
|
||||
me, ctx, ctx->sock);
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* void
|
||||
* ctl_endserver(ctx)
|
||||
* if the control listener is open, close it. clean out all eventlib
|
||||
* stuff. close all active sessions.
|
||||
*/
|
||||
void
|
||||
ctl_endserver(struct ctl_sctx *ctx) {
|
||||
static const char me[] = "ctl_endserver";
|
||||
struct ctl_sess *this, *next;
|
||||
|
||||
(*ctx->logger)(ctl_debug, "%s: ctx %p, sock %d, acID %p, sess %p",
|
||||
me, ctx, ctx->sock, ctx->acID.opaque, ctx->sess);
|
||||
if (ctx->acID.opaque != NULL) {
|
||||
(void)evCancelConn(ctx->ev, ctx->acID);
|
||||
ctx->acID.opaque = NULL;
|
||||
}
|
||||
if (ctx->sock != -1) {
|
||||
(void) close(ctx->sock);
|
||||
ctx->sock = -1;
|
||||
}
|
||||
for (this = HEAD(ctx->sess); this != NULL; this = next) {
|
||||
next = NEXT(this, link);
|
||||
ctl_close(this);
|
||||
}
|
||||
memput(ctx, sizeof *ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* If body is non-NULL then it we add a "." line after it.
|
||||
* Caller must have escaped lines with leading ".".
|
||||
*/
|
||||
void
|
||||
ctl_response(struct ctl_sess *sess, u_int code, const char *text,
|
||||
u_int flags, const void *respctx, ctl_srvrdone donefunc,
|
||||
void *uap, const char *body, size_t bodylen)
|
||||
{
|
||||
static const char me[] = "ctl_response";
|
||||
struct iovec iov[3], *iovp = iov;
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
char tmp[MAX_NTOP], *pc;
|
||||
int n;
|
||||
|
||||
REQUIRE(sess->state == initializing ||
|
||||
sess->state == processing ||
|
||||
sess->state == reading_data ||
|
||||
sess->state == writing);
|
||||
REQUIRE(sess->wrtiID.opaque == NULL);
|
||||
REQUIRE(sess->wrID.opaque == NULL);
|
||||
ctl_new_state(sess, writing, me);
|
||||
sess->donefunc = donefunc;
|
||||
sess->uap = uap;
|
||||
if (!allocated_p(sess->outbuf) &&
|
||||
ctl_bufget(&sess->outbuf, ctx->logger) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: cant get an output buffer",
|
||||
me, address_expr);
|
||||
goto untimely;
|
||||
}
|
||||
if (sizeof "000-\r\n" + strlen(text) > (size_t)MAX_LINELEN) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: output buffer ovf, closing",
|
||||
me, address_expr);
|
||||
goto untimely;
|
||||
}
|
||||
sess->outbuf.used = SPRINTF((sess->outbuf.text, "%03d%c%s\r\n",
|
||||
code, (flags & CTL_MORE) != 0 ? '-' : ' ',
|
||||
text));
|
||||
for (pc = sess->outbuf.text, n = 0;
|
||||
n < (int)sess->outbuf.used-2; pc++, n++)
|
||||
if (!isascii((unsigned char)*pc) ||
|
||||
!isprint((unsigned char)*pc))
|
||||
*pc = '\040';
|
||||
*iovp++ = evConsIovec(sess->outbuf.text, sess->outbuf.used);
|
||||
if (body != NULL) {
|
||||
char *tmp;
|
||||
DE_CONST(body, tmp);
|
||||
*iovp++ = evConsIovec(tmp, bodylen);
|
||||
DE_CONST(".\r\n", tmp);
|
||||
*iovp++ = evConsIovec(tmp, 3);
|
||||
}
|
||||
(*ctx->logger)(ctl_debug, "%s: [%d] %s", me,
|
||||
sess->outbuf.used, sess->outbuf.text);
|
||||
if (evWrite(ctx->ev, sess->sock, iov, iovp - iov,
|
||||
ctl_writedone, sess, &sess->wrID) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: evWrite: %s", me,
|
||||
address_expr, strerror(errno));
|
||||
goto untimely;
|
||||
}
|
||||
if (evSetIdleTimer(ctx->ev, ctl_wrtimeout, sess, ctx->timeout,
|
||||
&sess->wrtiID) < 0)
|
||||
{
|
||||
(*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me,
|
||||
address_expr, strerror(errno));
|
||||
goto untimely;
|
||||
}
|
||||
if (evTimeRW(ctx->ev, sess->wrID, sess->wrtiID) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: evTimeRW: %s", me,
|
||||
address_expr, strerror(errno));
|
||||
untimely:
|
||||
ctl_signal_done(ctx, sess);
|
||||
ctl_close(sess);
|
||||
return;
|
||||
}
|
||||
sess->respctx = respctx;
|
||||
sess->respflags = flags;
|
||||
}
|
||||
|
||||
void
|
||||
ctl_sendhelp(struct ctl_sess *sess, u_int code) {
|
||||
static const char me[] = "ctl_sendhelp";
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
|
||||
sess->helpcode = code;
|
||||
sess->verb = &fakehelpverb;
|
||||
ctl_morehelp(ctx, sess, NULL, me, CTL_MORE,
|
||||
(const void *)ctx->verbs, NULL);
|
||||
}
|
||||
|
||||
void *
|
||||
ctl_getcsctx(struct ctl_sess *sess) {
|
||||
return (sess->csctx);
|
||||
}
|
||||
|
||||
void *
|
||||
ctl_setcsctx(struct ctl_sess *sess, void *csctx) {
|
||||
void *old = sess->csctx;
|
||||
|
||||
sess->csctx = csctx;
|
||||
return (old);
|
||||
}
|
||||
|
||||
/* Private functions. */
|
||||
|
||||
static void
|
||||
ctl_accept(evContext lev, void *uap, int fd,
|
||||
const void *lav, int lalen,
|
||||
const void *rav, int ralen)
|
||||
{
|
||||
static const char me[] = "ctl_accept";
|
||||
struct ctl_sctx *ctx = uap;
|
||||
struct ctl_sess *sess = NULL;
|
||||
char tmp[MAX_NTOP];
|
||||
|
||||
UNUSED(lev);
|
||||
UNUSED(lalen);
|
||||
UNUSED(ralen);
|
||||
|
||||
if (fd < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: accept: %s",
|
||||
me, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (ctx->cur_sess == ctx->max_sess) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: too many control sessions",
|
||||
me, ctl_sa_ntop((const struct sockaddr *)rav,
|
||||
tmp, sizeof tmp,
|
||||
ctx->logger));
|
||||
(void) close(fd);
|
||||
return;
|
||||
}
|
||||
sess = memget(sizeof *sess);
|
||||
if (sess == NULL) {
|
||||
(*ctx->logger)(ctl_error, "%s: memget: %s", me,
|
||||
strerror(errno));
|
||||
(void) close(fd);
|
||||
return;
|
||||
}
|
||||
if (fcntl(fd, F_SETFD, 1) < 0) {
|
||||
(*ctx->logger)(ctl_warning, "%s: fcntl: %s", me,
|
||||
strerror(errno));
|
||||
}
|
||||
ctx->cur_sess++;
|
||||
INIT_LINK(sess, link);
|
||||
APPEND(ctx->sess, sess, link);
|
||||
sess->ctx = ctx;
|
||||
sess->sock = fd;
|
||||
sess->wrID.opaque = NULL;
|
||||
sess->rdID.opaque = NULL;
|
||||
sess->wrtiID.opaque = NULL;
|
||||
sess->rdtiID.opaque = NULL;
|
||||
sess->respctx = NULL;
|
||||
sess->csctx = NULL;
|
||||
if (((const struct sockaddr *)rav)->sa_family == AF_UNIX)
|
||||
ctl_sa_copy((const struct sockaddr *)lav,
|
||||
(struct sockaddr *)&sess->sa);
|
||||
else
|
||||
ctl_sa_copy((const struct sockaddr *)rav,
|
||||
(struct sockaddr *)&sess->sa);
|
||||
sess->donefunc = NULL;
|
||||
buffer_init(sess->inbuf);
|
||||
buffer_init(sess->outbuf);
|
||||
sess->state = available;
|
||||
ctl_new_state(sess, initializing, me);
|
||||
sess->verb = ctx->connverb;
|
||||
(*ctx->logger)(ctl_debug, "%s: %s: accepting (fd %d)",
|
||||
me, address_expr, sess->sock);
|
||||
(*ctx->connverb->func)(ctx, sess, ctx->connverb, "", 0,
|
||||
(const struct sockaddr *)rav, ctx->uctx);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_new_state(struct ctl_sess *sess, enum state new_state, const char *reason)
|
||||
{
|
||||
static const char me[] = "ctl_new_state";
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
char tmp[MAX_NTOP];
|
||||
|
||||
(*ctx->logger)(ctl_debug, "%s: %s: %s -> %s (%s)",
|
||||
me, address_expr,
|
||||
state_names[sess->state],
|
||||
state_names[new_state], reason);
|
||||
sess->state = new_state;
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_close(struct ctl_sess *sess) {
|
||||
static const char me[] = "ctl_close";
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
char tmp[MAX_NTOP];
|
||||
|
||||
REQUIRE(sess->state == initializing ||
|
||||
sess->state == writing ||
|
||||
sess->state == reading ||
|
||||
sess->state == processing ||
|
||||
sess->state == reading_data ||
|
||||
sess->state == idling);
|
||||
REQUIRE(sess->sock != -1);
|
||||
if (sess->state == reading || sess->state == reading_data)
|
||||
ctl_stop_read(sess);
|
||||
else if (sess->state == writing) {
|
||||
if (sess->wrID.opaque != NULL) {
|
||||
(void) evCancelRW(ctx->ev, sess->wrID);
|
||||
sess->wrID.opaque = NULL;
|
||||
}
|
||||
if (sess->wrtiID.opaque != NULL) {
|
||||
(void) evClearIdleTimer(ctx->ev, sess->wrtiID);
|
||||
sess->wrtiID.opaque = NULL;
|
||||
}
|
||||
}
|
||||
ctl_new_state(sess, closing, me);
|
||||
(void) close(sess->sock);
|
||||
if (allocated_p(sess->inbuf))
|
||||
ctl_bufput(&sess->inbuf);
|
||||
if (allocated_p(sess->outbuf))
|
||||
ctl_bufput(&sess->outbuf);
|
||||
(*ctx->logger)(ctl_debug, "%s: %s: closed (fd %d)",
|
||||
me, address_expr, sess->sock);
|
||||
UNLINK(ctx->sess, sess, link);
|
||||
memput(sess, sizeof *sess);
|
||||
ctx->cur_sess--;
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_start_read(struct ctl_sess *sess) {
|
||||
static const char me[] = "ctl_start_read";
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
char tmp[MAX_NTOP];
|
||||
|
||||
REQUIRE(sess->state == initializing ||
|
||||
sess->state == writing ||
|
||||
sess->state == processing ||
|
||||
sess->state == idling);
|
||||
REQUIRE(sess->rdtiID.opaque == NULL);
|
||||
REQUIRE(sess->rdID.opaque == NULL);
|
||||
sess->inbuf.used = 0;
|
||||
if (evSetIdleTimer(ctx->ev, ctl_rdtimeout, sess, ctx->timeout,
|
||||
&sess->rdtiID) < 0)
|
||||
{
|
||||
(*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me,
|
||||
address_expr, strerror(errno));
|
||||
ctl_close(sess);
|
||||
return;
|
||||
}
|
||||
if (evSelectFD(ctx->ev, sess->sock, EV_READ,
|
||||
ctl_readable, sess, &sess->rdID) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: evSelectFD: %s", me,
|
||||
address_expr, strerror(errno));
|
||||
return;
|
||||
}
|
||||
ctl_new_state(sess, reading, me);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_stop_read(struct ctl_sess *sess) {
|
||||
static const char me[] = "ctl_stop_read";
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
|
||||
REQUIRE(sess->state == reading || sess->state == reading_data);
|
||||
REQUIRE(sess->rdID.opaque != NULL);
|
||||
(void) evDeselectFD(ctx->ev, sess->rdID);
|
||||
sess->rdID.opaque = NULL;
|
||||
if (sess->rdtiID.opaque != NULL) {
|
||||
(void) evClearIdleTimer(ctx->ev, sess->rdtiID);
|
||||
sess->rdtiID.opaque = NULL;
|
||||
}
|
||||
ctl_new_state(sess, idling, me);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_readable(evContext lev, void *uap, int fd, int evmask) {
|
||||
static const char me[] = "ctl_readable";
|
||||
struct ctl_sess *sess = uap;
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
char *eos, tmp[MAX_NTOP];
|
||||
ssize_t n;
|
||||
|
||||
REQUIRE(sess != NULL);
|
||||
REQUIRE(fd >= 0);
|
||||
REQUIRE(evmask == EV_READ);
|
||||
REQUIRE(sess->state == reading || sess->state == reading_data);
|
||||
evTouchIdleTimer(lev, sess->rdtiID);
|
||||
if (!allocated_p(sess->inbuf) &&
|
||||
ctl_bufget(&sess->inbuf, ctx->logger) < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: cant get an input buffer",
|
||||
me, address_expr);
|
||||
ctl_close(sess);
|
||||
return;
|
||||
}
|
||||
n = read(sess->sock, sess->inbuf.text + sess->inbuf.used,
|
||||
MAX_LINELEN - sess->inbuf.used);
|
||||
if (n <= 0) {
|
||||
(*ctx->logger)(ctl_debug, "%s: %s: read: %s",
|
||||
me, address_expr,
|
||||
(n == 0) ? "Unexpected EOF" : strerror(errno));
|
||||
ctl_close(sess);
|
||||
return;
|
||||
}
|
||||
sess->inbuf.used += n;
|
||||
eos = memchr(sess->inbuf.text, '\n', sess->inbuf.used);
|
||||
if (eos != NULL && eos != sess->inbuf.text && eos[-1] == '\r') {
|
||||
eos[-1] = '\0';
|
||||
if ((sess->respflags & CTL_DATA) != 0) {
|
||||
INSIST(sess->verb != NULL);
|
||||
(*sess->verb->func)(sess->ctx, sess, sess->verb,
|
||||
sess->inbuf.text,
|
||||
CTL_DATA, sess->respctx,
|
||||
sess->ctx->uctx);
|
||||
} else {
|
||||
ctl_stop_read(sess);
|
||||
ctl_docommand(sess);
|
||||
}
|
||||
sess->inbuf.used -= ((eos - sess->inbuf.text) + 1);
|
||||
if (sess->inbuf.used == 0U)
|
||||
ctl_bufput(&sess->inbuf);
|
||||
else
|
||||
memmove(sess->inbuf.text, eos + 1, sess->inbuf.used);
|
||||
return;
|
||||
}
|
||||
if (sess->inbuf.used == (size_t)MAX_LINELEN) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: line too long, closing",
|
||||
me, address_expr);
|
||||
ctl_close(sess);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_wrtimeout(evContext lev, void *uap,
|
||||
struct timespec due,
|
||||
struct timespec itv)
|
||||
{
|
||||
static const char me[] = "ctl_wrtimeout";
|
||||
struct ctl_sess *sess = uap;
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
char tmp[MAX_NTOP];
|
||||
|
||||
UNUSED(lev);
|
||||
UNUSED(due);
|
||||
UNUSED(itv);
|
||||
|
||||
REQUIRE(sess->state == writing);
|
||||
sess->wrtiID.opaque = NULL;
|
||||
(*ctx->logger)(ctl_warning, "%s: %s: write timeout, closing",
|
||||
me, address_expr);
|
||||
if (sess->wrID.opaque != NULL) {
|
||||
(void) evCancelRW(ctx->ev, sess->wrID);
|
||||
sess->wrID.opaque = NULL;
|
||||
}
|
||||
ctl_signal_done(ctx, sess);
|
||||
ctl_new_state(sess, processing, me);
|
||||
ctl_close(sess);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_rdtimeout(evContext lev, void *uap,
|
||||
struct timespec due,
|
||||
struct timespec itv)
|
||||
{
|
||||
static const char me[] = "ctl_rdtimeout";
|
||||
struct ctl_sess *sess = uap;
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
char tmp[MAX_NTOP];
|
||||
|
||||
UNUSED(lev);
|
||||
UNUSED(due);
|
||||
UNUSED(itv);
|
||||
|
||||
REQUIRE(sess->state == reading);
|
||||
sess->rdtiID.opaque = NULL;
|
||||
(*ctx->logger)(ctl_warning, "%s: %s: timeout, closing",
|
||||
me, address_expr);
|
||||
if (sess->state == reading || sess->state == reading_data)
|
||||
ctl_stop_read(sess);
|
||||
ctl_signal_done(ctx, sess);
|
||||
ctl_new_state(sess, processing, me);
|
||||
ctl_response(sess, ctx->timeoutcode, "Timeout.", CTL_EXIT, NULL,
|
||||
NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_docommand(struct ctl_sess *sess) {
|
||||
static const char me[] = "ctl_docommand";
|
||||
char *name, *rest, tmp[MAX_NTOP];
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
const struct ctl_verb *verb;
|
||||
|
||||
REQUIRE(allocated_p(sess->inbuf));
|
||||
(*ctx->logger)(ctl_debug, "%s: %s: \"%s\" [%u]",
|
||||
me, address_expr,
|
||||
sess->inbuf.text, (u_int)sess->inbuf.used);
|
||||
ctl_new_state(sess, processing, me);
|
||||
name = sess->inbuf.text + strspn(sess->inbuf.text, space);
|
||||
rest = name + strcspn(name, space);
|
||||
if (*rest != '\0') {
|
||||
*rest++ = '\0';
|
||||
rest += strspn(rest, space);
|
||||
}
|
||||
for (verb = ctx->verbs;
|
||||
verb != NULL && verb->name != NULL && verb->func != NULL;
|
||||
verb++)
|
||||
if (verb->name[0] != '\0' && strcasecmp(name, verb->name) == 0)
|
||||
break;
|
||||
if (verb != NULL && verb->name != NULL && verb->func != NULL) {
|
||||
sess->verb = verb;
|
||||
(*verb->func)(ctx, sess, verb, rest, 0, NULL, ctx->uctx);
|
||||
} else {
|
||||
char buf[1100];
|
||||
|
||||
if (sizeof "Unrecognized command \"\" (args \"\")" +
|
||||
strlen(name) + strlen(rest) > sizeof buf)
|
||||
strcpy(buf, "Unrecognized command (buf ovf)");
|
||||
else
|
||||
sprintf(buf,
|
||||
"Unrecognized command \"%s\" (args \"%s\")",
|
||||
name, rest);
|
||||
ctl_response(sess, ctx->unkncode, buf, 0, NULL, NULL, NULL,
|
||||
NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_writedone(evContext lev, void *uap, int fd, int bytes) {
|
||||
static const char me[] = "ctl_writedone";
|
||||
struct ctl_sess *sess = uap;
|
||||
struct ctl_sctx *ctx = sess->ctx;
|
||||
char tmp[MAX_NTOP];
|
||||
int save_errno = errno;
|
||||
|
||||
UNUSED(lev);
|
||||
UNUSED(uap);
|
||||
|
||||
REQUIRE(sess->state == writing);
|
||||
REQUIRE(fd == sess->sock);
|
||||
REQUIRE(sess->wrtiID.opaque != NULL);
|
||||
sess->wrID.opaque = NULL;
|
||||
(void) evClearIdleTimer(ctx->ev, sess->wrtiID);
|
||||
sess->wrtiID.opaque = NULL;
|
||||
if (bytes < 0) {
|
||||
(*ctx->logger)(ctl_error, "%s: %s: %s",
|
||||
me, address_expr, strerror(save_errno));
|
||||
ctl_close(sess);
|
||||
return;
|
||||
}
|
||||
|
||||
INSIST(allocated_p(sess->outbuf));
|
||||
ctl_bufput(&sess->outbuf);
|
||||
if ((sess->respflags & CTL_EXIT) != 0) {
|
||||
ctl_signal_done(ctx, sess);
|
||||
ctl_close(sess);
|
||||
return;
|
||||
} else if ((sess->respflags & CTL_MORE) != 0) {
|
||||
INSIST(sess->verb != NULL);
|
||||
(*sess->verb->func)(sess->ctx, sess, sess->verb, "",
|
||||
CTL_MORE, sess->respctx, sess->ctx->uctx);
|
||||
} else {
|
||||
ctl_signal_done(ctx, sess);
|
||||
ctl_start_read(sess);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_morehelp(struct ctl_sctx *ctx, struct ctl_sess *sess,
|
||||
const struct ctl_verb *verb, const char *text,
|
||||
u_int respflags, const void *respctx, void *uctx)
|
||||
{
|
||||
const struct ctl_verb *this = respctx, *next = this + 1;
|
||||
|
||||
UNUSED(ctx);
|
||||
UNUSED(verb);
|
||||
UNUSED(text);
|
||||
UNUSED(uctx);
|
||||
|
||||
REQUIRE(!lastverb_p(this));
|
||||
REQUIRE((respflags & CTL_MORE) != 0);
|
||||
if (lastverb_p(next))
|
||||
respflags &= ~CTL_MORE;
|
||||
ctl_response(sess, sess->helpcode, this->help, respflags, next,
|
||||
NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ctl_signal_done(struct ctl_sctx *ctx, struct ctl_sess *sess) {
|
||||
if (sess->donefunc != NULL) {
|
||||
(*sess->donefunc)(ctx, sess, sess->uap);
|
||||
sess->donefunc = NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,367 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1995-1999 by Internet Software Consortium
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* ev_connects.c - implement asynch connect/accept for the eventlib
|
||||
* vix 16sep96 [initial]
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Import. */
|
||||
|
||||
#include "port_before.h"
|
||||
#include "fd_setsize.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/eventlib.h>
|
||||
#include <isc/assertions.h>
|
||||
#include "eventlib_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Macros. */
|
||||
|
||||
#define GETXXXNAME(f, s, sa, len) ( \
|
||||
(f((s), (&sa), (&len)) >= 0) ? 0 : \
|
||||
(errno != EAFNOSUPPORT && errno != EOPNOTSUPP) ? -1 : ( \
|
||||
memset(&(sa), 0, sizeof (sa)), \
|
||||
(len) = sizeof (sa), \
|
||||
(sa).sa_family = AF_UNIX, \
|
||||
0 \
|
||||
) \
|
||||
)
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void listener(evContext ctx, void *uap, int fd, int evmask);
|
||||
static void connector(evContext ctx, void *uap, int fd, int evmask);
|
||||
|
||||
/* Public. */
|
||||
|
||||
int
|
||||
evListen(evContext opaqueCtx, int fd, int maxconn,
|
||||
evConnFunc func, void *uap, evConnID *id)
|
||||
{
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evConn *new;
|
||||
int mode;
|
||||
|
||||
OKNEW(new);
|
||||
new->flags = EV_CONN_LISTEN;
|
||||
OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */
|
||||
/*
|
||||
* Remember the nonblocking status. We assume that either evSelectFD
|
||||
* has not been done to this fd, or that if it has then the caller
|
||||
* will evCancelConn before they evDeselectFD. If our assumptions
|
||||
* are not met, then we might restore the old nonblocking status
|
||||
* incorrectly.
|
||||
*/
|
||||
if ((mode & PORT_NONBLOCK) == 0) {
|
||||
#ifdef USE_FIONBIO_IOCTL
|
||||
int on = 1;
|
||||
OK(ioctl(fd, FIONBIO, (char *)&on));
|
||||
#else
|
||||
OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK));
|
||||
#endif
|
||||
new->flags |= EV_CONN_BLOCK;
|
||||
}
|
||||
OK(listen(fd, maxconn));
|
||||
if (evSelectFD(opaqueCtx, fd, EV_READ, listener, new, &new->file) < 0){
|
||||
int save = errno;
|
||||
|
||||
FREE(new);
|
||||
errno = save;
|
||||
return (-1);
|
||||
}
|
||||
new->flags |= EV_CONN_SELECTED;
|
||||
new->func = func;
|
||||
new->uap = uap;
|
||||
new->fd = fd;
|
||||
if (ctx->conns != NULL)
|
||||
ctx->conns->prev = new;
|
||||
new->prev = NULL;
|
||||
new->next = ctx->conns;
|
||||
ctx->conns = new;
|
||||
if (id)
|
||||
id->opaque = new;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evConnect(evContext opaqueCtx, int fd, const void *ra, int ralen,
|
||||
evConnFunc func, void *uap, evConnID *id)
|
||||
{
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evConn *new;
|
||||
|
||||
OKNEW(new);
|
||||
new->flags = 0;
|
||||
/* Do the select() first to get the socket into nonblocking mode. */
|
||||
if (evSelectFD(opaqueCtx, fd, EV_MASK_ALL,
|
||||
connector, new, &new->file) < 0) {
|
||||
int save = errno;
|
||||
|
||||
FREE(new);
|
||||
errno = save;
|
||||
return (-1);
|
||||
}
|
||||
new->flags |= EV_CONN_SELECTED;
|
||||
if (connect(fd, ra, ralen) < 0 &&
|
||||
errno != EWOULDBLOCK &&
|
||||
errno != EAGAIN &&
|
||||
errno != EINPROGRESS) {
|
||||
int save = errno;
|
||||
|
||||
(void) evDeselectFD(opaqueCtx, new->file);
|
||||
FREE(new);
|
||||
errno = save;
|
||||
return (-1);
|
||||
}
|
||||
/* No error, or EWOULDBLOCK. select() tells when it's ready. */
|
||||
new->func = func;
|
||||
new->uap = uap;
|
||||
new->fd = fd;
|
||||
if (ctx->conns != NULL)
|
||||
ctx->conns->prev = new;
|
||||
new->prev = NULL;
|
||||
new->next = ctx->conns;
|
||||
ctx->conns = new;
|
||||
if (id)
|
||||
id->opaque = new;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evCancelConn(evContext opaqueCtx, evConnID id) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evConn *this = id.opaque;
|
||||
evAccept *acc, *nxtacc;
|
||||
int mode;
|
||||
|
||||
if ((this->flags & EV_CONN_SELECTED) != 0)
|
||||
(void) evDeselectFD(opaqueCtx, this->file);
|
||||
if ((this->flags & EV_CONN_BLOCK) != 0) {
|
||||
mode = fcntl(this->fd, F_GETFL, NULL);
|
||||
if (mode == -1) {
|
||||
if (errno != EBADF)
|
||||
return (-1);
|
||||
} else {
|
||||
#ifdef USE_FIONBIO_IOCTL
|
||||
int on = 1;
|
||||
OK(ioctl(this->fd, FIONBIO, (char *)&on));
|
||||
#else
|
||||
OK(fcntl(this->fd, F_SETFL, mode | PORT_NONBLOCK));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlink from ctx->conns. */
|
||||
if (this->prev != NULL)
|
||||
this->prev->next = this->next;
|
||||
else
|
||||
ctx->conns = this->next;
|
||||
if (this->next != NULL)
|
||||
this->next->prev = this->prev;
|
||||
|
||||
/*
|
||||
* Remove `this' from the ctx->accepts list (zero or more times).
|
||||
*/
|
||||
for (acc = HEAD(ctx->accepts), nxtacc = NULL;
|
||||
acc != NULL;
|
||||
acc = nxtacc)
|
||||
{
|
||||
nxtacc = NEXT(acc, link);
|
||||
if (acc->conn == this) {
|
||||
UNLINK(ctx->accepts, acc, link);
|
||||
close(acc->fd);
|
||||
FREE(acc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wrap up and get out. */
|
||||
FREE(this);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int evHold(evContext opaqueCtx, evConnID id) {
|
||||
evConn *this = id.opaque;
|
||||
|
||||
if ((this->flags & EV_CONN_LISTEN) == 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if ((this->flags & EV_CONN_SELECTED) == 0)
|
||||
return (0);
|
||||
this->flags &= ~EV_CONN_SELECTED;
|
||||
return (evDeselectFD(opaqueCtx, this->file));
|
||||
}
|
||||
|
||||
int evUnhold(evContext opaqueCtx, evConnID id) {
|
||||
evConn *this = id.opaque;
|
||||
int ret;
|
||||
|
||||
if ((this->flags & EV_CONN_LISTEN) == 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if ((this->flags & EV_CONN_SELECTED) != 0)
|
||||
return (0);
|
||||
ret = evSelectFD(opaqueCtx, this->fd, EV_READ, listener, this,
|
||||
&this->file);
|
||||
if (ret == 0)
|
||||
this->flags |= EV_CONN_SELECTED;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
evTryAccept(evContext opaqueCtx, evConnID id, int *sys_errno) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evConn *conn = id.opaque;
|
||||
evAccept *new;
|
||||
|
||||
if ((conn->flags & EV_CONN_LISTEN) == 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
OKNEW(new);
|
||||
new->conn = conn;
|
||||
new->ralen = sizeof new->ra;
|
||||
new->fd = accept(conn->fd, &new->ra.sa, &new->ralen);
|
||||
if (new->fd > ctx->highestFD) {
|
||||
close(new->fd);
|
||||
new->fd = -1;
|
||||
new->ioErrno = ENOTSOCK;
|
||||
}
|
||||
if (new->fd >= 0) {
|
||||
new->lalen = sizeof new->la;
|
||||
if (GETXXXNAME(getsockname, new->fd, new->la.sa, new->lalen) < 0) {
|
||||
new->ioErrno = errno;
|
||||
(void) close(new->fd);
|
||||
new->fd = -1;
|
||||
} else
|
||||
new->ioErrno = 0;
|
||||
} else {
|
||||
new->ioErrno = errno;
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
FREE(new);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
INIT_LINK(new, link);
|
||||
APPEND(ctx->accepts, new, link);
|
||||
*sys_errno = new->ioErrno;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
static void
|
||||
listener(evContext opaqueCtx, void *uap, int fd, int evmask) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evConn *conn = uap;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in in;
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
struct sockaddr_un un;
|
||||
#endif
|
||||
} la, ra;
|
||||
int new;
|
||||
ISC_SOCKLEN_T lalen = 0, ralen;
|
||||
|
||||
REQUIRE((evmask & EV_READ) != 0);
|
||||
ralen = sizeof ra;
|
||||
new = accept(fd, &ra.sa, &ralen);
|
||||
if (new > ctx->highestFD) {
|
||||
close(new);
|
||||
new = -1;
|
||||
errno = ENOTSOCK;
|
||||
}
|
||||
if (new >= 0) {
|
||||
lalen = sizeof la;
|
||||
if (GETXXXNAME(getsockname, new, la.sa, lalen) < 0) {
|
||||
int save = errno;
|
||||
|
||||
(void) close(new);
|
||||
errno = save;
|
||||
new = -1;
|
||||
}
|
||||
} else if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
return;
|
||||
(*conn->func)(opaqueCtx, conn->uap, new, &la.sa, lalen, &ra.sa, ralen);
|
||||
}
|
||||
|
||||
static void
|
||||
connector(evContext opaqueCtx, void *uap, int fd, int evmask) {
|
||||
evConn *conn = uap;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in in;
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
struct sockaddr_un un;
|
||||
#endif
|
||||
} la, ra;
|
||||
ISC_SOCKLEN_T lalen, ralen;
|
||||
#ifndef NETREAD_BROKEN
|
||||
char buf[1];
|
||||
#endif
|
||||
void *conn_uap;
|
||||
evConnFunc conn_func;
|
||||
evConnID id;
|
||||
int socket_errno = 0;
|
||||
ISC_SOCKLEN_T optlen;
|
||||
|
||||
UNUSED(evmask);
|
||||
|
||||
lalen = sizeof la;
|
||||
ralen = sizeof ra;
|
||||
conn_uap = conn->uap;
|
||||
conn_func = conn->func;
|
||||
id.opaque = conn;
|
||||
#ifdef SO_ERROR
|
||||
optlen = sizeof socket_errno;
|
||||
if (fd < 0 &&
|
||||
getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char *)&socket_errno,
|
||||
&optlen) < 0)
|
||||
socket_errno = errno;
|
||||
else
|
||||
errno = socket_errno;
|
||||
#endif
|
||||
if (evCancelConn(opaqueCtx, id) < 0 ||
|
||||
socket_errno ||
|
||||
#ifdef NETREAD_BROKEN
|
||||
0 ||
|
||||
#else
|
||||
read(fd, buf, 0) < 0 ||
|
||||
#endif
|
||||
GETXXXNAME(getsockname, fd, la.sa, lalen) < 0 ||
|
||||
GETXXXNAME(getpeername, fd, ra.sa, ralen) < 0) {
|
||||
int save = errno;
|
||||
|
||||
(void) close(fd); /* XXX closing caller's fd */
|
||||
errno = save;
|
||||
fd = -1;
|
||||
}
|
||||
(*conn_func)(opaqueCtx, conn_uap, fd, &la.sa, lalen, &ra.sa, ralen);
|
||||
}
|
||||
@@ -1,283 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1995-1999 by Internet Software Consortium
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* ev_files.c - implement asynch file IO for the eventlib
|
||||
* vix 11sep95 [initial]
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
#include "fd_setsize.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/eventlib.h>
|
||||
#include "eventlib_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
static evFile *FindFD(const evContext_p *ctx, int fd, int eventmask);
|
||||
|
||||
int
|
||||
evSelectFD(evContext opaqueCtx,
|
||||
int fd,
|
||||
int eventmask,
|
||||
evFileFunc func,
|
||||
void *uap,
|
||||
evFileID *opaqueID
|
||||
) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evFile *id;
|
||||
int mode;
|
||||
|
||||
evPrintf(ctx, 1,
|
||||
"evSelectFD(ctx %p, fd %d, mask 0x%x, func %p, uap %p)\n",
|
||||
ctx, fd, eventmask, func, uap);
|
||||
if (eventmask == 0 || (eventmask & ~EV_MASK_ALL) != 0)
|
||||
EV_ERR(EINVAL);
|
||||
if (fd > ctx->highestFD)
|
||||
EV_ERR(EINVAL);
|
||||
OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */
|
||||
|
||||
/*
|
||||
* The first time we touch a file descriptor, we need to check to see
|
||||
* if the application already had it in O_NONBLOCK mode and if so, all
|
||||
* of our deselect()'s have to leave it in O_NONBLOCK. If not, then
|
||||
* all but our last deselect() has to leave it in O_NONBLOCK.
|
||||
*/
|
||||
id = FindFD(ctx, fd, EV_MASK_ALL);
|
||||
if (id == NULL) {
|
||||
if (mode & PORT_NONBLOCK)
|
||||
FD_SET(fd, &ctx->nonblockBefore);
|
||||
else {
|
||||
#ifdef USE_FIONBIO_IOCTL
|
||||
int on = 1;
|
||||
OK(ioctl(fd, FIONBIO, (char *)&on));
|
||||
#else
|
||||
OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK));
|
||||
#endif
|
||||
FD_CLR(fd, &ctx->nonblockBefore);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this descriptor is already in use, search for it again to see
|
||||
* if any of the eventmask bits we want to set are already captured.
|
||||
* We cannot usefully capture the same fd event more than once in the
|
||||
* same context.
|
||||
*/
|
||||
if (id != NULL && FindFD(ctx, fd, eventmask) != NULL)
|
||||
EV_ERR(ETOOMANYREFS);
|
||||
|
||||
/* Allocate and fill. */
|
||||
OKNEW(id);
|
||||
id->func = func;
|
||||
id->uap = uap;
|
||||
id->fd = fd;
|
||||
id->eventmask = eventmask;
|
||||
|
||||
/*
|
||||
* Insert at head. Order could be important for performance if we
|
||||
* believe that evGetNext()'s accesses to the fd_sets will be more
|
||||
* serial and therefore more cache-lucky if the list is ordered by
|
||||
* ``fd.'' We do not believe these things, so we don't do it.
|
||||
*
|
||||
* The interesting sequence is where GetNext() has cached a select()
|
||||
* result and the caller decides to evSelectFD() on some descriptor.
|
||||
* Since GetNext() starts at the head, it can miss new entries we add
|
||||
* at the head. This is not a serious problem since the event being
|
||||
* evSelectFD()'d for has to occur before evSelectFD() is called for
|
||||
* the file event to be considered "missed" -- a real corner case.
|
||||
* Maintaining a "tail" pointer for ctx->files would fix this, but I'm
|
||||
* not sure it would be ``more correct.''
|
||||
*/
|
||||
if (ctx->files != NULL)
|
||||
ctx->files->prev = id;
|
||||
id->prev = NULL;
|
||||
id->next = ctx->files;
|
||||
ctx->files = id;
|
||||
|
||||
/* Insert into fd table. */
|
||||
if (ctx->fdTable[fd] != NULL)
|
||||
ctx->fdTable[fd]->fdprev = id;
|
||||
id->fdprev = NULL;
|
||||
id->fdnext = ctx->fdTable[fd];
|
||||
ctx->fdTable[fd] = id;
|
||||
|
||||
/* Turn on the appropriate bits in the {rd,wr,ex}Next fd_set's. */
|
||||
if (eventmask & EV_READ)
|
||||
FD_SET(fd, &ctx->rdNext);
|
||||
if (eventmask & EV_WRITE)
|
||||
FD_SET(fd, &ctx->wrNext);
|
||||
if (eventmask & EV_EXCEPT)
|
||||
FD_SET(fd, &ctx->exNext);
|
||||
|
||||
/* Update fdMax. */
|
||||
if (fd > ctx->fdMax)
|
||||
ctx->fdMax = fd;
|
||||
|
||||
/* Remember the ID if the caller provided us a place for it. */
|
||||
if (opaqueID)
|
||||
opaqueID->opaque = id;
|
||||
|
||||
evPrintf(ctx, 5,
|
||||
"evSelectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n",
|
||||
fd, eventmask,
|
||||
(u_long)ctx->rdNext.fds_bits[0],
|
||||
(u_long)ctx->wrNext.fds_bits[0],
|
||||
(u_long)ctx->exNext.fds_bits[0]);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evDeselectFD(evContext opaqueCtx, evFileID opaqueID) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evFile *del = opaqueID.opaque;
|
||||
evFile *cur;
|
||||
int mode, eventmask;
|
||||
|
||||
if (!del) {
|
||||
evPrintf(ctx, 11, "evDeselectFD(NULL) ignored\n");
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
evPrintf(ctx, 1, "evDeselectFD(fd %d, mask 0x%x)\n",
|
||||
del->fd, del->eventmask);
|
||||
|
||||
/* Get the mode. Unless the file has been closed, errors are bad. */
|
||||
mode = fcntl(del->fd, F_GETFL, NULL);
|
||||
if (mode == -1 && errno != EBADF)
|
||||
EV_ERR(errno);
|
||||
|
||||
/* Remove from the list of files. */
|
||||
if (del->prev != NULL)
|
||||
del->prev->next = del->next;
|
||||
else
|
||||
ctx->files = del->next;
|
||||
if (del->next != NULL)
|
||||
del->next->prev = del->prev;
|
||||
|
||||
/* Remove from the fd table. */
|
||||
if (del->fdprev != NULL)
|
||||
del->fdprev->fdnext = del->fdnext;
|
||||
else
|
||||
ctx->fdTable[del->fd] = del->fdnext;
|
||||
if (del->fdnext != NULL)
|
||||
del->fdnext->fdprev = del->fdprev;
|
||||
|
||||
/*
|
||||
* If the file descriptor does not appear in any other select() entry,
|
||||
* and if !EV_WASNONBLOCK, and if we got no EBADF when we got the mode
|
||||
* earlier, then: restore the fd to blocking status.
|
||||
*/
|
||||
if (!(cur = FindFD(ctx, del->fd, EV_MASK_ALL)) &&
|
||||
!FD_ISSET(del->fd, &ctx->nonblockBefore) &&
|
||||
mode != -1) {
|
||||
/*
|
||||
* Note that we won't return an error status to the caller if
|
||||
* this fcntl() fails since (a) we've already done the work
|
||||
* and (b) the caller didn't ask us anything about O_NONBLOCK.
|
||||
*/
|
||||
#ifdef USE_FIONBIO_IOCTL
|
||||
int off = 1;
|
||||
(void) ioctl(del->fd, FIONBIO, (char *)&off);
|
||||
#else
|
||||
(void) fcntl(del->fd, F_SETFL, mode & ~PORT_NONBLOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Now find all other uses of this descriptor and OR together an event
|
||||
* mask so that we don't turn off {rd,wr,ex}Next bits that some other
|
||||
* file event is using. As an optimization, stop if the event mask
|
||||
* fills.
|
||||
*/
|
||||
eventmask = 0;
|
||||
for ((void)NULL;
|
||||
cur != NULL && eventmask != EV_MASK_ALL;
|
||||
cur = cur->next)
|
||||
if (cur->fd == del->fd)
|
||||
eventmask |= cur->eventmask;
|
||||
|
||||
/* OK, now we know which bits we can clear out. */
|
||||
if (!(eventmask & EV_READ)) {
|
||||
FD_CLR(del->fd, &ctx->rdNext);
|
||||
if (FD_ISSET(del->fd, &ctx->rdLast)) {
|
||||
FD_CLR(del->fd, &ctx->rdLast);
|
||||
ctx->fdCount--;
|
||||
}
|
||||
}
|
||||
if (!(eventmask & EV_WRITE)) {
|
||||
FD_CLR(del->fd, &ctx->wrNext);
|
||||
if (FD_ISSET(del->fd, &ctx->wrLast)) {
|
||||
FD_CLR(del->fd, &ctx->wrLast);
|
||||
ctx->fdCount--;
|
||||
}
|
||||
}
|
||||
if (!(eventmask & EV_EXCEPT)) {
|
||||
FD_CLR(del->fd, &ctx->exNext);
|
||||
if (FD_ISSET(del->fd, &ctx->exLast)) {
|
||||
FD_CLR(del->fd, &ctx->exLast);
|
||||
ctx->fdCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this was the maxFD, find the new one. */
|
||||
if (del->fd == ctx->fdMax) {
|
||||
ctx->fdMax = -1;
|
||||
for (cur = ctx->files; cur; cur = cur->next)
|
||||
if (cur->fd > ctx->fdMax)
|
||||
ctx->fdMax = cur->fd;
|
||||
}
|
||||
|
||||
/* If this was the fdNext, cycle that to the next entry. */
|
||||
if (del == ctx->fdNext)
|
||||
ctx->fdNext = del->next;
|
||||
|
||||
evPrintf(ctx, 5,
|
||||
"evDeselectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n",
|
||||
del->fd, eventmask,
|
||||
(u_long)ctx->rdNext.fds_bits[0],
|
||||
(u_long)ctx->wrNext.fds_bits[0],
|
||||
(u_long)ctx->exNext.fds_bits[0]);
|
||||
|
||||
/* Couldn't free it before now since we were using fields out of it. */
|
||||
FREE(del);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static evFile *
|
||||
FindFD(const evContext_p *ctx, int fd, int eventmask) {
|
||||
evFile *id;
|
||||
|
||||
for (id = ctx->fdTable[fd]; id != NULL; id = id->fdnext)
|
||||
if (id->fd == fd && (id->eventmask & eventmask) != 0)
|
||||
break;
|
||||
return (id);
|
||||
}
|
||||
@@ -1,306 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* ev_streams.c - implement asynch stream file IO for the eventlib
|
||||
* vix 04mar96 [initial]
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
#include "fd_setsize.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <isc/eventlib.h>
|
||||
#include <isc/assertions.h>
|
||||
#include "eventlib_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
static int copyvec(evStream *str, const struct iovec *iov, int iocnt);
|
||||
static void consume(evStream *str, size_t bytes);
|
||||
static void done(evContext opaqueCtx, evStream *str);
|
||||
static void writable(evContext opaqueCtx, void *uap, int fd, int evmask);
|
||||
static void readable(evContext opaqueCtx, void *uap, int fd, int evmask);
|
||||
|
||||
struct iovec
|
||||
evConsIovec(void *buf, size_t cnt) {
|
||||
struct iovec ret;
|
||||
|
||||
memset(&ret, 0xf5, sizeof ret);
|
||||
ret.iov_base = buf;
|
||||
ret.iov_len = cnt;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt,
|
||||
evStreamFunc func, void *uap, evStreamID *id)
|
||||
{
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evStream *new;
|
||||
int save;
|
||||
|
||||
OKNEW(new);
|
||||
new->func = func;
|
||||
new->uap = uap;
|
||||
new->fd = fd;
|
||||
new->flags = 0;
|
||||
if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0)
|
||||
goto free;
|
||||
if (copyvec(new, iov, iocnt) < 0)
|
||||
goto free;
|
||||
new->prevDone = NULL;
|
||||
new->nextDone = NULL;
|
||||
if (ctx->streams != NULL)
|
||||
ctx->streams->prev = new;
|
||||
new->prev = NULL;
|
||||
new->next = ctx->streams;
|
||||
ctx->streams = new;
|
||||
if (id != NULL)
|
||||
id->opaque = new;
|
||||
return (0);
|
||||
free:
|
||||
save = errno;
|
||||
FREE(new);
|
||||
errno = save;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt,
|
||||
evStreamFunc func, void *uap, evStreamID *id)
|
||||
{
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evStream *new;
|
||||
int save;
|
||||
|
||||
OKNEW(new);
|
||||
new->func = func;
|
||||
new->uap = uap;
|
||||
new->fd = fd;
|
||||
new->flags = 0;
|
||||
if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0)
|
||||
goto free;
|
||||
if (copyvec(new, iov, iocnt) < 0)
|
||||
goto free;
|
||||
new->prevDone = NULL;
|
||||
new->nextDone = NULL;
|
||||
if (ctx->streams != NULL)
|
||||
ctx->streams->prev = new;
|
||||
new->prev = NULL;
|
||||
new->next = ctx->streams;
|
||||
ctx->streams = new;
|
||||
if (id)
|
||||
id->opaque = new;
|
||||
return (0);
|
||||
free:
|
||||
save = errno;
|
||||
FREE(new);
|
||||
errno = save;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ {
|
||||
evStream *str = id.opaque;
|
||||
|
||||
UNUSED(opaqueCtx);
|
||||
|
||||
str->timer = timer;
|
||||
str->flags |= EV_STR_TIMEROK;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ {
|
||||
evStream *str = id.opaque;
|
||||
|
||||
UNUSED(opaqueCtx);
|
||||
|
||||
str->flags &= ~EV_STR_TIMEROK;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evCancelRW(evContext opaqueCtx, evStreamID id) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evStream *old = id.opaque;
|
||||
|
||||
/*
|
||||
* The streams list is doubly threaded. First, there's ctx->streams
|
||||
* that's used by evDestroy() to find and cancel all streams. Second,
|
||||
* there's ctx->strDone (head) and ctx->strLast (tail) which thread
|
||||
* through the potentially smaller number of "IO completed" streams,
|
||||
* used in evGetNext() to avoid scanning the entire list.
|
||||
*/
|
||||
|
||||
/* Unlink from ctx->streams. */
|
||||
if (old->prev != NULL)
|
||||
old->prev->next = old->next;
|
||||
else
|
||||
ctx->streams = old->next;
|
||||
if (old->next != NULL)
|
||||
old->next->prev = old->prev;
|
||||
|
||||
/*
|
||||
* If 'old' is on the ctx->strDone list, remove it. Update
|
||||
* ctx->strLast if necessary.
|
||||
*/
|
||||
if (old->prevDone == NULL && old->nextDone == NULL) {
|
||||
/*
|
||||
* Either 'old' is the only item on the done list, or it's
|
||||
* not on the done list. If the former, then we unlink it
|
||||
* from the list. If the latter, we leave the list alone.
|
||||
*/
|
||||
if (ctx->strDone == old) {
|
||||
ctx->strDone = NULL;
|
||||
ctx->strLast = NULL;
|
||||
}
|
||||
} else {
|
||||
if (old->prevDone != NULL)
|
||||
old->prevDone->nextDone = old->nextDone;
|
||||
else
|
||||
ctx->strDone = old->nextDone;
|
||||
if (old->nextDone != NULL)
|
||||
old->nextDone->prevDone = old->prevDone;
|
||||
else
|
||||
ctx->strLast = old->prevDone;
|
||||
}
|
||||
|
||||
/* Deallocate the stream. */
|
||||
if (old->file.opaque)
|
||||
evDeselectFD(opaqueCtx, old->file);
|
||||
memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount);
|
||||
FREE(old);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Copy a scatter/gather vector and initialize a stream handler's IO. */
|
||||
static int
|
||||
copyvec(evStream *str, const struct iovec *iov, int iocnt) {
|
||||
int i;
|
||||
|
||||
str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt);
|
||||
if (str->iovOrig == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
str->ioTotal = 0;
|
||||
for (i = 0; i < iocnt; i++) {
|
||||
str->iovOrig[i] = iov[i];
|
||||
str->ioTotal += iov[i].iov_len;
|
||||
}
|
||||
str->iovOrigCount = iocnt;
|
||||
str->iovCur = str->iovOrig;
|
||||
str->iovCurCount = str->iovOrigCount;
|
||||
str->ioDone = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Pull off or truncate lead iovec(s). */
|
||||
static void
|
||||
consume(evStream *str, size_t bytes) {
|
||||
while (bytes > 0U) {
|
||||
if (bytes < (size_t)str->iovCur->iov_len) {
|
||||
str->iovCur->iov_len -= bytes;
|
||||
str->iovCur->iov_base = (void *)
|
||||
((u_char *)str->iovCur->iov_base + bytes);
|
||||
str->ioDone += bytes;
|
||||
bytes = 0;
|
||||
} else {
|
||||
bytes -= str->iovCur->iov_len;
|
||||
str->ioDone += str->iovCur->iov_len;
|
||||
str->iovCur++;
|
||||
str->iovCurCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a stream to Done list and deselect the FD. */
|
||||
static void
|
||||
done(evContext opaqueCtx, evStream *str) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
|
||||
if (ctx->strLast != NULL) {
|
||||
str->prevDone = ctx->strLast;
|
||||
ctx->strLast->nextDone = str;
|
||||
ctx->strLast = str;
|
||||
} else {
|
||||
INSIST(ctx->strDone == NULL);
|
||||
ctx->strDone = ctx->strLast = str;
|
||||
}
|
||||
evDeselectFD(opaqueCtx, str->file);
|
||||
str->file.opaque = NULL;
|
||||
/* evDrop() will call evCancelRW() on us. */
|
||||
}
|
||||
|
||||
/* Dribble out some bytes on the stream. (Called by evDispatch().) */
|
||||
static void
|
||||
writable(evContext opaqueCtx, void *uap, int fd, int evmask) {
|
||||
evStream *str = uap;
|
||||
int bytes;
|
||||
|
||||
UNUSED(evmask);
|
||||
|
||||
bytes = writev(fd, str->iovCur, str->iovCurCount);
|
||||
if (bytes > 0) {
|
||||
if ((str->flags & EV_STR_TIMEROK) != 0)
|
||||
evTouchIdleTimer(opaqueCtx, str->timer);
|
||||
consume(str, bytes);
|
||||
} else {
|
||||
if (bytes < 0 && errno != EINTR) {
|
||||
str->ioDone = -1;
|
||||
str->ioErrno = errno;
|
||||
}
|
||||
}
|
||||
if (str->ioDone == -1 || str->ioDone == str->ioTotal)
|
||||
done(opaqueCtx, str);
|
||||
}
|
||||
|
||||
/* Scoop up some bytes from the stream. (Called by evDispatch().) */
|
||||
static void
|
||||
readable(evContext opaqueCtx, void *uap, int fd, int evmask) {
|
||||
evStream *str = uap;
|
||||
int bytes;
|
||||
|
||||
UNUSED(evmask);
|
||||
|
||||
bytes = readv(fd, str->iovCur, str->iovCurCount);
|
||||
if (bytes > 0) {
|
||||
if ((str->flags & EV_STR_TIMEROK) != 0)
|
||||
evTouchIdleTimer(opaqueCtx, str->timer);
|
||||
consume(str, bytes);
|
||||
} else {
|
||||
if (bytes == 0)
|
||||
str->ioDone = 0;
|
||||
else {
|
||||
if (errno != EINTR) {
|
||||
str->ioDone = -1;
|
||||
str->ioErrno = errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (str->ioDone <= 0 || str->ioDone == str->ioTotal)
|
||||
done(opaqueCtx, str);
|
||||
}
|
||||
@@ -1,497 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1995-1999 by Internet Software Consortium
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* ev_timers.c - implement timers for the eventlib
|
||||
* vix 09sep95 [initial]
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/* Import. */
|
||||
|
||||
#include "port_before.h"
|
||||
#include "fd_setsize.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <isc/eventlib.h>
|
||||
#include "eventlib_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Constants. */
|
||||
|
||||
#define MILLION 1000000
|
||||
#define BILLION 1000000000
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static int due_sooner(void *, void *);
|
||||
static void set_index(void *, int);
|
||||
static void free_timer(void *, void *);
|
||||
static void print_timer(void *, void *);
|
||||
static void idle_timeout(evContext, void *, struct timespec, struct timespec);
|
||||
|
||||
/* Private type. */
|
||||
|
||||
typedef struct {
|
||||
evTimerFunc func;
|
||||
void * uap;
|
||||
struct timespec lastTouched;
|
||||
struct timespec max_idle;
|
||||
evTimer * timer;
|
||||
} idle_timer;
|
||||
|
||||
/* Public. */
|
||||
|
||||
struct timespec
|
||||
evConsTime(time_t sec, long nsec) {
|
||||
struct timespec x;
|
||||
|
||||
x.tv_sec = sec;
|
||||
x.tv_nsec = nsec;
|
||||
return (x);
|
||||
}
|
||||
|
||||
struct timespec
|
||||
evAddTime(struct timespec addend1, struct timespec addend2) {
|
||||
struct timespec x;
|
||||
|
||||
x.tv_sec = addend1.tv_sec + addend2.tv_sec;
|
||||
x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec;
|
||||
if (x.tv_nsec >= BILLION) {
|
||||
x.tv_sec++;
|
||||
x.tv_nsec -= BILLION;
|
||||
}
|
||||
return (x);
|
||||
}
|
||||
|
||||
struct timespec
|
||||
evSubTime(struct timespec minuend, struct timespec subtrahend) {
|
||||
struct timespec x;
|
||||
|
||||
x.tv_sec = minuend.tv_sec - subtrahend.tv_sec;
|
||||
if (minuend.tv_nsec >= subtrahend.tv_nsec)
|
||||
x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec;
|
||||
else {
|
||||
x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec;
|
||||
x.tv_sec--;
|
||||
}
|
||||
return (x);
|
||||
}
|
||||
|
||||
int
|
||||
evCmpTime(struct timespec a, struct timespec b) {
|
||||
long x = a.tv_sec - b.tv_sec;
|
||||
|
||||
if (x == 0L)
|
||||
x = a.tv_nsec - b.tv_nsec;
|
||||
return (x < 0L ? (-1) : x > 0L ? (1) : (0));
|
||||
}
|
||||
|
||||
struct timespec
|
||||
evNowTime() {
|
||||
struct timeval now;
|
||||
#ifdef CLOCK_REALTIME
|
||||
struct timespec tsnow;
|
||||
int m = CLOCK_REALTIME;
|
||||
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
if (__evOptMonoTime)
|
||||
m = CLOCK_MONOTONIC;
|
||||
#endif
|
||||
if (clock_gettime(m, &tsnow) == 0)
|
||||
return (tsnow);
|
||||
#endif
|
||||
if (gettimeofday(&now, NULL) < 0)
|
||||
return (evConsTime(0, 0));
|
||||
return (evTimeSpec(now));
|
||||
}
|
||||
|
||||
struct timespec
|
||||
evUTCTime() {
|
||||
struct timeval now;
|
||||
#ifdef CLOCK_REALTIME
|
||||
struct timespec tsnow;
|
||||
if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0)
|
||||
return (tsnow);
|
||||
#endif
|
||||
if (gettimeofday(&now, NULL) < 0)
|
||||
return (evConsTime(0, 0));
|
||||
return (evTimeSpec(now));
|
||||
}
|
||||
|
||||
struct timespec
|
||||
evLastEventTime(evContext opaqueCtx) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
|
||||
return (ctx->lastEventTime);
|
||||
}
|
||||
|
||||
struct timespec
|
||||
evTimeSpec(struct timeval tv) {
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
return (ts);
|
||||
}
|
||||
|
||||
struct timeval
|
||||
evTimeVal(struct timespec ts) {
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = ts.tv_sec;
|
||||
tv.tv_usec = ts.tv_nsec / 1000;
|
||||
return (tv);
|
||||
}
|
||||
|
||||
int
|
||||
evSetTimer(evContext opaqueCtx,
|
||||
evTimerFunc func,
|
||||
void *uap,
|
||||
struct timespec due,
|
||||
struct timespec inter,
|
||||
evTimerID *opaqueID
|
||||
) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evTimer *id;
|
||||
|
||||
evPrintf(ctx, 1,
|
||||
"evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n",
|
||||
ctx, func, uap,
|
||||
(long)due.tv_sec, due.tv_nsec,
|
||||
(long)inter.tv_sec, inter.tv_nsec);
|
||||
|
||||
#ifdef __hpux
|
||||
/*
|
||||
* tv_sec and tv_nsec are unsigned.
|
||||
*/
|
||||
if (due.tv_nsec >= BILLION)
|
||||
EV_ERR(EINVAL);
|
||||
|
||||
if (inter.tv_nsec >= BILLION)
|
||||
EV_ERR(EINVAL);
|
||||
#else
|
||||
if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
|
||||
EV_ERR(EINVAL);
|
||||
|
||||
if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
|
||||
EV_ERR(EINVAL);
|
||||
#endif
|
||||
|
||||
/* due={0,0} is a magic cookie meaning "now." */
|
||||
if (due.tv_sec == (time_t)0 && due.tv_nsec == 0L)
|
||||
due = evNowTime();
|
||||
|
||||
/* Allocate and fill. */
|
||||
OKNEW(id);
|
||||
id->func = func;
|
||||
id->uap = uap;
|
||||
id->due = due;
|
||||
id->inter = inter;
|
||||
|
||||
if (heap_insert(ctx->timers, id) < 0)
|
||||
return (-1);
|
||||
|
||||
/* Remember the ID if the caller provided us a place for it. */
|
||||
if (opaqueID)
|
||||
opaqueID->opaque = id;
|
||||
|
||||
if (ctx->debug > 7) {
|
||||
evPrintf(ctx, 7, "timers after evSetTimer:\n");
|
||||
(void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evClearTimer(evContext opaqueCtx, evTimerID id) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evTimer *del = id.opaque;
|
||||
|
||||
if (ctx->cur != NULL &&
|
||||
ctx->cur->type == Timer &&
|
||||
ctx->cur->u.timer.this == del) {
|
||||
evPrintf(ctx, 8, "deferring delete of timer (executing)\n");
|
||||
/*
|
||||
* Setting the interval to zero ensures that evDrop() will
|
||||
* clean up the timer.
|
||||
*/
|
||||
del->inter = evConsTime(0, 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (heap_element(ctx->timers, del->index) != del)
|
||||
EV_ERR(ENOENT);
|
||||
|
||||
if (heap_delete(ctx->timers, del->index) < 0)
|
||||
return (-1);
|
||||
FREE(del);
|
||||
|
||||
if (ctx->debug > 7) {
|
||||
evPrintf(ctx, 7, "timers after evClearTimer:\n");
|
||||
(void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evConfigTimer(evContext opaqueCtx,
|
||||
evTimerID id,
|
||||
const char *param,
|
||||
int value
|
||||
) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evTimer *timer = id.opaque;
|
||||
int result=0;
|
||||
|
||||
UNUSED(value);
|
||||
|
||||
if (heap_element(ctx->timers, timer->index) != timer)
|
||||
EV_ERR(ENOENT);
|
||||
|
||||
if (strcmp(param, "rate") == 0)
|
||||
timer->mode |= EV_TMR_RATE;
|
||||
else if (strcmp(param, "interval") == 0)
|
||||
timer->mode &= ~EV_TMR_RATE;
|
||||
else
|
||||
EV_ERR(EINVAL);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int
|
||||
evResetTimer(evContext opaqueCtx,
|
||||
evTimerID id,
|
||||
evTimerFunc func,
|
||||
void *uap,
|
||||
struct timespec due,
|
||||
struct timespec inter
|
||||
) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evTimer *timer = id.opaque;
|
||||
struct timespec old_due;
|
||||
int result=0;
|
||||
|
||||
if (heap_element(ctx->timers, timer->index) != timer)
|
||||
EV_ERR(ENOENT);
|
||||
|
||||
#ifdef __hpux
|
||||
/*
|
||||
* tv_sec and tv_nsec are unsigned.
|
||||
*/
|
||||
if (due.tv_nsec >= BILLION)
|
||||
EV_ERR(EINVAL);
|
||||
|
||||
if (inter.tv_nsec >= BILLION)
|
||||
EV_ERR(EINVAL);
|
||||
#else
|
||||
if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
|
||||
EV_ERR(EINVAL);
|
||||
|
||||
if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
|
||||
EV_ERR(EINVAL);
|
||||
#endif
|
||||
|
||||
old_due = timer->due;
|
||||
|
||||
timer->func = func;
|
||||
timer->uap = uap;
|
||||
timer->due = due;
|
||||
timer->inter = inter;
|
||||
|
||||
switch (evCmpTime(due, old_due)) {
|
||||
case -1:
|
||||
result = heap_increased(ctx->timers, timer->index);
|
||||
break;
|
||||
case 0:
|
||||
result = 0;
|
||||
break;
|
||||
case 1:
|
||||
result = heap_decreased(ctx->timers, timer->index);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctx->debug > 7) {
|
||||
evPrintf(ctx, 7, "timers after evResetTimer:\n");
|
||||
(void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
int
|
||||
evSetIdleTimer(evContext opaqueCtx,
|
||||
evTimerFunc func,
|
||||
void *uap,
|
||||
struct timespec max_idle,
|
||||
evTimerID *opaqueID
|
||||
) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
idle_timer *tt;
|
||||
|
||||
/* Allocate and fill. */
|
||||
OKNEW(tt);
|
||||
tt->func = func;
|
||||
tt->uap = uap;
|
||||
tt->lastTouched = ctx->lastEventTime;
|
||||
tt->max_idle = max_idle;
|
||||
|
||||
if (evSetTimer(opaqueCtx, idle_timeout, tt,
|
||||
evAddTime(ctx->lastEventTime, max_idle),
|
||||
max_idle, opaqueID) < 0) {
|
||||
FREE(tt);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tt->timer = opaqueID->opaque;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evClearIdleTimer(evContext opaqueCtx, evTimerID id) {
|
||||
evTimer *del = id.opaque;
|
||||
idle_timer *tt = del->uap;
|
||||
|
||||
FREE(tt);
|
||||
return (evClearTimer(opaqueCtx, id));
|
||||
}
|
||||
|
||||
int
|
||||
evResetIdleTimer(evContext opaqueCtx,
|
||||
evTimerID opaqueID,
|
||||
evTimerFunc func,
|
||||
void *uap,
|
||||
struct timespec max_idle
|
||||
) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evTimer *timer = opaqueID.opaque;
|
||||
idle_timer *tt = timer->uap;
|
||||
|
||||
tt->func = func;
|
||||
tt->uap = uap;
|
||||
tt->lastTouched = ctx->lastEventTime;
|
||||
tt->max_idle = max_idle;
|
||||
|
||||
return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt,
|
||||
evAddTime(ctx->lastEventTime, max_idle),
|
||||
max_idle));
|
||||
}
|
||||
|
||||
int
|
||||
evTouchIdleTimer(evContext opaqueCtx, evTimerID id) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evTimer *t = id.opaque;
|
||||
idle_timer *tt = t->uap;
|
||||
|
||||
tt->lastTouched = ctx->lastEventTime;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Public to the rest of eventlib. */
|
||||
|
||||
heap_context
|
||||
evCreateTimers(const evContext_p *ctx) {
|
||||
|
||||
UNUSED(ctx);
|
||||
|
||||
return (heap_new(due_sooner, set_index, 2048));
|
||||
}
|
||||
|
||||
void
|
||||
evDestroyTimers(const evContext_p *ctx) {
|
||||
(void) heap_for_each(ctx->timers, free_timer, NULL);
|
||||
(void) heap_free(ctx->timers);
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
static int
|
||||
due_sooner(void *a, void *b) {
|
||||
evTimer *a_timer, *b_timer;
|
||||
|
||||
a_timer = a;
|
||||
b_timer = b;
|
||||
return (evCmpTime(a_timer->due, b_timer->due) < 0);
|
||||
}
|
||||
|
||||
static void
|
||||
set_index(void *what, int index) {
|
||||
evTimer *timer;
|
||||
|
||||
timer = what;
|
||||
timer->index = index;
|
||||
}
|
||||
|
||||
static void
|
||||
free_timer(void *what, void *uap) {
|
||||
evTimer *t = what;
|
||||
|
||||
UNUSED(uap);
|
||||
|
||||
FREE(t);
|
||||
}
|
||||
|
||||
static void
|
||||
print_timer(void *what, void *uap) {
|
||||
evTimer *cur = what;
|
||||
evContext_p *ctx = uap;
|
||||
|
||||
cur = what;
|
||||
evPrintf(ctx, 7,
|
||||
" func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n",
|
||||
cur->func, cur->uap,
|
||||
(long)cur->due.tv_sec, cur->due.tv_nsec,
|
||||
(long)cur->inter.tv_sec, cur->inter.tv_nsec);
|
||||
}
|
||||
|
||||
static void
|
||||
idle_timeout(evContext opaqueCtx,
|
||||
void *uap,
|
||||
struct timespec due,
|
||||
struct timespec inter
|
||||
) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
idle_timer *this = uap;
|
||||
struct timespec idle;
|
||||
|
||||
UNUSED(due);
|
||||
UNUSED(inter);
|
||||
|
||||
idle = evSubTime(ctx->lastEventTime, this->lastTouched);
|
||||
if (evCmpTime(idle, this->max_idle) >= 0) {
|
||||
(this->func)(opaqueCtx, this->uap, this->timer->due,
|
||||
this->max_idle);
|
||||
/*
|
||||
* Setting the interval to zero will cause the timer to
|
||||
* be cleaned up in evDrop().
|
||||
*/
|
||||
this->timer->inter = evConsTime(0, 0);
|
||||
FREE(this);
|
||||
} else {
|
||||
/* evDrop() will reschedule the timer. */
|
||||
this->timer->inter = evSubTime(this->max_idle, idle);
|
||||
}
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* ev_waits.c - implement deferred function calls for the eventlib
|
||||
* vix 05dec95 [initial]
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
#include "fd_setsize.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <isc/eventlib.h>
|
||||
#include <isc/assertions.h>
|
||||
#include "eventlib_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static void print_waits(evContext_p *ctx);
|
||||
static evWaitList * evNewWaitList(evContext_p *);
|
||||
static void evFreeWaitList(evContext_p *, evWaitList *);
|
||||
static evWaitList * evGetWaitList(evContext_p *, const void *, int);
|
||||
|
||||
|
||||
/* Public. */
|
||||
|
||||
/*
|
||||
* Enter a new wait function on the queue.
|
||||
*/
|
||||
int
|
||||
evWaitFor(evContext opaqueCtx, const void *tag,
|
||||
evWaitFunc func, void *uap, evWaitID *id)
|
||||
{
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evWait *new;
|
||||
evWaitList *wl = evGetWaitList(ctx, tag, 1);
|
||||
|
||||
OKNEW(new);
|
||||
new->func = func;
|
||||
new->uap = uap;
|
||||
new->tag = tag;
|
||||
new->next = NULL;
|
||||
if (wl->last != NULL)
|
||||
wl->last->next = new;
|
||||
else
|
||||
wl->first = new;
|
||||
wl->last = new;
|
||||
if (id != NULL)
|
||||
id->opaque = new;
|
||||
if (ctx->debug >= 9)
|
||||
print_waits(ctx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark runnable all waiting functions having a certain tag.
|
||||
*/
|
||||
int
|
||||
evDo(evContext opaqueCtx, const void *tag) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evWaitList *wl = evGetWaitList(ctx, tag, 0);
|
||||
evWait *first;
|
||||
|
||||
if (!wl) {
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
first = wl->first;
|
||||
INSIST(first != NULL);
|
||||
|
||||
if (ctx->waitDone.last != NULL)
|
||||
ctx->waitDone.last->next = first;
|
||||
else
|
||||
ctx->waitDone.first = first;
|
||||
ctx->waitDone.last = wl->last;
|
||||
evFreeWaitList(ctx, wl);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a waiting (or ready to run) function from the queue.
|
||||
*/
|
||||
int
|
||||
evUnwait(evContext opaqueCtx, evWaitID id) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evWait *this, *prev;
|
||||
evWaitList *wl;
|
||||
int found = 0;
|
||||
|
||||
this = id.opaque;
|
||||
INSIST(this != NULL);
|
||||
wl = evGetWaitList(ctx, this->tag, 0);
|
||||
if (wl != NULL) {
|
||||
for (prev = NULL, this = wl->first;
|
||||
this != NULL;
|
||||
prev = this, this = this->next)
|
||||
if (this == (evWait *)id.opaque) {
|
||||
found = 1;
|
||||
if (prev != NULL)
|
||||
prev->next = this->next;
|
||||
else
|
||||
wl->first = this->next;
|
||||
if (wl->last == this)
|
||||
wl->last = prev;
|
||||
if (wl->first == NULL)
|
||||
evFreeWaitList(ctx, wl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
/* Maybe it's done */
|
||||
for (prev = NULL, this = ctx->waitDone.first;
|
||||
this != NULL;
|
||||
prev = this, this = this->next)
|
||||
if (this == (evWait *)id.opaque) {
|
||||
found = 1;
|
||||
if (prev != NULL)
|
||||
prev->next = this->next;
|
||||
else
|
||||
ctx->waitDone.first = this->next;
|
||||
if (ctx->waitDone.last == this)
|
||||
ctx->waitDone.last = prev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
FREE(this);
|
||||
|
||||
if (ctx->debug >= 9)
|
||||
print_waits(ctx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evWait *new;
|
||||
|
||||
OKNEW(new);
|
||||
new->func = func;
|
||||
new->uap = uap;
|
||||
new->tag = NULL;
|
||||
new->next = NULL;
|
||||
if (ctx->waitDone.last != NULL)
|
||||
ctx->waitDone.last->next = new;
|
||||
else
|
||||
ctx->waitDone.first = new;
|
||||
ctx->waitDone.last = new;
|
||||
if (ctx->debug >= 9)
|
||||
print_waits(ctx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
static void
|
||||
print_waits(evContext_p *ctx) {
|
||||
evWaitList *wl;
|
||||
evWait *this;
|
||||
|
||||
evPrintf(ctx, 9, "wait waiting:\n");
|
||||
for (wl = ctx->waitLists; wl != NULL; wl = wl->next) {
|
||||
INSIST(wl->first != NULL);
|
||||
evPrintf(ctx, 9, " tag %p:", wl->first->tag);
|
||||
for (this = wl->first; this != NULL; this = this->next)
|
||||
evPrintf(ctx, 9, " %p", this);
|
||||
evPrintf(ctx, 9, "\n");
|
||||
}
|
||||
evPrintf(ctx, 9, "wait done:");
|
||||
for (this = ctx->waitDone.first; this != NULL; this = this->next)
|
||||
evPrintf(ctx, 9, " %p", this);
|
||||
evPrintf(ctx, 9, "\n");
|
||||
}
|
||||
|
||||
static evWaitList *
|
||||
evNewWaitList(evContext_p *ctx) {
|
||||
evWaitList *new;
|
||||
|
||||
NEW(new);
|
||||
if (new == NULL)
|
||||
return (NULL);
|
||||
new->first = new->last = NULL;
|
||||
new->prev = NULL;
|
||||
new->next = ctx->waitLists;
|
||||
if (new->next != NULL)
|
||||
new->next->prev = new;
|
||||
ctx->waitLists = new;
|
||||
return (new);
|
||||
}
|
||||
|
||||
static void
|
||||
evFreeWaitList(evContext_p *ctx, evWaitList *this) {
|
||||
|
||||
INSIST(this != NULL);
|
||||
|
||||
if (this->prev != NULL)
|
||||
this->prev->next = this->next;
|
||||
else
|
||||
ctx->waitLists = this->next;
|
||||
if (this->next != NULL)
|
||||
this->next->prev = this->prev;
|
||||
FREE(this);
|
||||
}
|
||||
|
||||
static evWaitList *
|
||||
evGetWaitList(evContext_p *ctx, const void *tag, int should_create) {
|
||||
evWaitList *this;
|
||||
|
||||
for (this = ctx->waitLists; this != NULL; this = this->next) {
|
||||
if (this->first != NULL && this->first->tag == tag)
|
||||
break;
|
||||
}
|
||||
if (this == NULL && should_create)
|
||||
this = evNewWaitList(ctx);
|
||||
return (this);
|
||||
}
|
||||
@@ -1,732 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1995-1999 by Internet Software Consortium
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* eventlib.c - implement glue for the eventlib
|
||||
* vix 09sep95 [initial]
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include "port_before.h"
|
||||
#include "fd_setsize.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/eventlib.h>
|
||||
#include <isc/assertions.h>
|
||||
#include "eventlib_p.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
int __evOptMonoTime;
|
||||
|
||||
/* Forward. */
|
||||
|
||||
#ifdef NEED_PSELECT
|
||||
static int pselect(int, void *, void *, void *,
|
||||
struct timespec *,
|
||||
const sigset_t *);
|
||||
#endif
|
||||
|
||||
int __evOptMonoTime;
|
||||
|
||||
/* Public. */
|
||||
|
||||
int
|
||||
evCreate(evContext *opaqueCtx) {
|
||||
evContext_p *ctx;
|
||||
|
||||
/* Make sure the memory heap is initialized. */
|
||||
if (meminit(0, 0) < 0 && errno != EEXIST)
|
||||
return (-1);
|
||||
|
||||
OKNEW(ctx);
|
||||
|
||||
/* Global. */
|
||||
ctx->cur = NULL;
|
||||
|
||||
/* Debugging. */
|
||||
ctx->debug = 0;
|
||||
ctx->output = NULL;
|
||||
|
||||
/* Connections. */
|
||||
ctx->conns = NULL;
|
||||
INIT_LIST(ctx->accepts);
|
||||
|
||||
/* Files. */
|
||||
ctx->files = NULL;
|
||||
FD_ZERO(&ctx->rdNext);
|
||||
FD_ZERO(&ctx->wrNext);
|
||||
FD_ZERO(&ctx->exNext);
|
||||
FD_ZERO(&ctx->nonblockBefore);
|
||||
ctx->fdMax = -1;
|
||||
ctx->fdNext = NULL;
|
||||
ctx->fdCount = 0; /* Invalidate {rd,wr,ex}Last. */
|
||||
ctx->highestFD = FD_SETSIZE - 1;
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
ctx->lastFdCount = 0;
|
||||
#endif
|
||||
memset(ctx->fdTable, 0, sizeof ctx->fdTable);
|
||||
|
||||
/* Streams. */
|
||||
ctx->streams = NULL;
|
||||
ctx->strDone = NULL;
|
||||
ctx->strLast = NULL;
|
||||
|
||||
/* Timers. */
|
||||
ctx->lastEventTime = evNowTime();
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
ctx->lastSelectTime = ctx->lastEventTime;
|
||||
#endif
|
||||
ctx->timers = evCreateTimers(ctx);
|
||||
if (ctx->timers == NULL)
|
||||
return (-1);
|
||||
|
||||
/* Waits. */
|
||||
ctx->waitLists = NULL;
|
||||
ctx->waitDone.first = ctx->waitDone.last = NULL;
|
||||
ctx->waitDone.prev = ctx->waitDone.next = NULL;
|
||||
|
||||
opaqueCtx->opaque = ctx;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
evSetDebug(evContext opaqueCtx, int level, FILE *output) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
|
||||
ctx->debug = level;
|
||||
ctx->output = output;
|
||||
}
|
||||
|
||||
int
|
||||
evDestroy(evContext opaqueCtx) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
int revs = 424242; /* Doug Adams. */
|
||||
evWaitList *this_wl, *next_wl;
|
||||
evWait *this_wait, *next_wait;
|
||||
|
||||
/* Connections. */
|
||||
while (revs-- > 0 && ctx->conns != NULL) {
|
||||
evConnID id;
|
||||
|
||||
id.opaque = ctx->conns;
|
||||
(void) evCancelConn(opaqueCtx, id);
|
||||
}
|
||||
INSIST(revs >= 0);
|
||||
|
||||
/* Streams. */
|
||||
while (revs-- > 0 && ctx->streams != NULL) {
|
||||
evStreamID id;
|
||||
|
||||
id.opaque = ctx->streams;
|
||||
(void) evCancelRW(opaqueCtx, id);
|
||||
}
|
||||
|
||||
/* Files. */
|
||||
while (revs-- > 0 && ctx->files != NULL) {
|
||||
evFileID id;
|
||||
|
||||
id.opaque = ctx->files;
|
||||
(void) evDeselectFD(opaqueCtx, id);
|
||||
}
|
||||
INSIST(revs >= 0);
|
||||
|
||||
/* Timers. */
|
||||
evDestroyTimers(ctx);
|
||||
|
||||
/* Waits. */
|
||||
for (this_wl = ctx->waitLists;
|
||||
revs-- > 0 && this_wl != NULL;
|
||||
this_wl = next_wl) {
|
||||
next_wl = this_wl->next;
|
||||
for (this_wait = this_wl->first;
|
||||
revs-- > 0 && this_wait != NULL;
|
||||
this_wait = next_wait) {
|
||||
next_wait = this_wait->next;
|
||||
FREE(this_wait);
|
||||
}
|
||||
FREE(this_wl);
|
||||
}
|
||||
for (this_wait = ctx->waitDone.first;
|
||||
revs-- > 0 && this_wait != NULL;
|
||||
this_wait = next_wait) {
|
||||
next_wait = this_wait->next;
|
||||
FREE(this_wait);
|
||||
}
|
||||
|
||||
FREE(ctx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
struct timespec nextTime;
|
||||
evTimer *nextTimer;
|
||||
evEvent_p *new;
|
||||
int x, pselect_errno, timerPast;
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
struct timespec interval;
|
||||
#endif
|
||||
|
||||
/* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */
|
||||
x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0);
|
||||
if (x != 1)
|
||||
EV_ERR(EINVAL);
|
||||
|
||||
/* Get the time of day. We'll do this again after select() blocks. */
|
||||
ctx->lastEventTime = evNowTime();
|
||||
|
||||
again:
|
||||
/* Finished accept()'s do not require a select(). */
|
||||
if (!EMPTY(ctx->accepts)) {
|
||||
OKNEW(new);
|
||||
new->type = Accept;
|
||||
new->u.accept.this = HEAD(ctx->accepts);
|
||||
UNLINK(ctx->accepts, HEAD(ctx->accepts), link);
|
||||
opaqueEv->opaque = new;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Stream IO does not require a select(). */
|
||||
if (ctx->strDone != NULL) {
|
||||
OKNEW(new);
|
||||
new->type = Stream;
|
||||
new->u.stream.this = ctx->strDone;
|
||||
ctx->strDone = ctx->strDone->nextDone;
|
||||
if (ctx->strDone == NULL)
|
||||
ctx->strLast = NULL;
|
||||
opaqueEv->opaque = new;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Waits do not require a select(). */
|
||||
if (ctx->waitDone.first != NULL) {
|
||||
OKNEW(new);
|
||||
new->type = Wait;
|
||||
new->u.wait.this = ctx->waitDone.first;
|
||||
ctx->waitDone.first = ctx->waitDone.first->next;
|
||||
if (ctx->waitDone.first == NULL)
|
||||
ctx->waitDone.last = NULL;
|
||||
opaqueEv->opaque = new;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Get the status and content of the next timer. */
|
||||
if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) {
|
||||
nextTime = nextTimer->due;
|
||||
timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0);
|
||||
} else
|
||||
timerPast = 0; /* Make gcc happy. */
|
||||
|
||||
evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount);
|
||||
if (ctx->fdCount == 0) {
|
||||
static const struct timespec NoTime = {0, 0L};
|
||||
enum { JustPoll, Block, Timer } m;
|
||||
struct timespec t, *tp;
|
||||
|
||||
/* Are there any events at all? */
|
||||
if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1)
|
||||
EV_ERR(ENOENT);
|
||||
|
||||
/* Figure out what select()'s timeout parameter should be. */
|
||||
if ((options & EV_POLL) != 0) {
|
||||
m = JustPoll;
|
||||
t = NoTime;
|
||||
tp = &t;
|
||||
} else if (nextTimer == NULL) {
|
||||
m = Block;
|
||||
/* ``t'' unused. */
|
||||
tp = NULL;
|
||||
} else if (timerPast) {
|
||||
m = JustPoll;
|
||||
t = NoTime;
|
||||
tp = &t;
|
||||
} else {
|
||||
m = Timer;
|
||||
/* ``t'' filled in later. */
|
||||
tp = &t;
|
||||
}
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
if (ctx->debug > 0) {
|
||||
interval = evSubTime(ctx->lastEventTime,
|
||||
ctx->lastSelectTime);
|
||||
if (interval.tv_sec > 0 || interval.tv_nsec > 0)
|
||||
evPrintf(ctx, 1,
|
||||
"time between pselect() %u.%09u count %d\n",
|
||||
interval.tv_sec, interval.tv_nsec,
|
||||
ctx->lastFdCount);
|
||||
}
|
||||
#endif
|
||||
do {
|
||||
/* XXX need to copy only the bits we are using. */
|
||||
ctx->rdLast = ctx->rdNext;
|
||||
ctx->wrLast = ctx->wrNext;
|
||||
ctx->exLast = ctx->exNext;
|
||||
|
||||
if (m == Timer) {
|
||||
INSIST(tp == &t);
|
||||
t = evSubTime(nextTime, ctx->lastEventTime);
|
||||
}
|
||||
|
||||
evPrintf(ctx, 4,
|
||||
"pselect(%d, 0x%lx, 0x%lx, 0x%lx, %ld.%09ld)\n",
|
||||
ctx->fdMax+1,
|
||||
(u_long)ctx->rdLast.fds_bits[0],
|
||||
(u_long)ctx->wrLast.fds_bits[0],
|
||||
(u_long)ctx->exLast.fds_bits[0],
|
||||
tp ? (long)tp->tv_sec : -1L,
|
||||
tp ? tp->tv_nsec : -1);
|
||||
|
||||
/* XXX should predict system's earliness and adjust. */
|
||||
x = pselect(ctx->fdMax+1,
|
||||
&ctx->rdLast, &ctx->wrLast, &ctx->exLast,
|
||||
tp, NULL);
|
||||
pselect_errno = errno;
|
||||
|
||||
evPrintf(ctx, 4, "select() returns %d (err: %s)\n",
|
||||
x, (x == -1) ? strerror(errno) : "none");
|
||||
|
||||
/* Anything but a poll can change the time. */
|
||||
if (m != JustPoll)
|
||||
ctx->lastEventTime = evNowTime();
|
||||
|
||||
/* Select() likes to finish about 10ms early. */
|
||||
} while (x == 0 && m == Timer &&
|
||||
evCmpTime(ctx->lastEventTime, nextTime) < 0);
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
ctx->lastSelectTime = ctx->lastEventTime;
|
||||
#endif
|
||||
if (x < 0) {
|
||||
if (pselect_errno == EINTR) {
|
||||
if ((options & EV_NULL) != 0)
|
||||
goto again;
|
||||
OKNEW(new);
|
||||
new->type = Null;
|
||||
/* No data. */
|
||||
opaqueEv->opaque = new;
|
||||
return (0);
|
||||
}
|
||||
if (pselect_errno == EBADF) {
|
||||
for (x = 0; x <= ctx->fdMax; x++) {
|
||||
struct stat sb;
|
||||
|
||||
if (FD_ISSET(x, &ctx->rdNext) == 0 &&
|
||||
FD_ISSET(x, &ctx->wrNext) == 0 &&
|
||||
FD_ISSET(x, &ctx->exNext) == 0)
|
||||
continue;
|
||||
if (fstat(x, &sb) == -1 &&
|
||||
errno == EBADF)
|
||||
evPrintf(ctx, 1, "EBADF: %d\n",
|
||||
x);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
EV_ERR(pselect_errno);
|
||||
}
|
||||
if (x == 0 && (nextTimer == NULL || !timerPast) &&
|
||||
(options & EV_POLL))
|
||||
EV_ERR(EWOULDBLOCK);
|
||||
ctx->fdCount = x;
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
ctx->lastFdCount = x;
|
||||
#endif
|
||||
}
|
||||
INSIST(nextTimer || ctx->fdCount);
|
||||
|
||||
/* Timers go first since we'd like them to be accurate. */
|
||||
if (nextTimer && !timerPast) {
|
||||
/* Has anything happened since we blocked? */
|
||||
timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0);
|
||||
}
|
||||
if (nextTimer && timerPast) {
|
||||
OKNEW(new);
|
||||
new->type = Timer;
|
||||
new->u.timer.this = nextTimer;
|
||||
opaqueEv->opaque = new;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* No timers, so there should be a ready file descriptor. */
|
||||
x = 0;
|
||||
while (ctx->fdCount > 0) {
|
||||
evFile *fid;
|
||||
int fd, eventmask;
|
||||
|
||||
if (ctx->fdNext == NULL) {
|
||||
if (++x == 2) {
|
||||
/*
|
||||
* Hitting the end twice means that the last
|
||||
* select() found some FD's which have since
|
||||
* been deselected.
|
||||
*
|
||||
* On some systems, the count returned by
|
||||
* selects is the total number of bits in
|
||||
* all masks that are set, and on others it's
|
||||
* the number of fd's that have some bit set,
|
||||
* and on others, it's just broken. We
|
||||
* always assume that it's the number of
|
||||
* bits set in all masks, because that's what
|
||||
* the man page says it should do, and
|
||||
* the worst that can happen is we do an
|
||||
* extra select().
|
||||
*/
|
||||
ctx->fdCount = 0;
|
||||
break;
|
||||
}
|
||||
ctx->fdNext = ctx->files;
|
||||
}
|
||||
fid = ctx->fdNext;
|
||||
ctx->fdNext = fid->next;
|
||||
|
||||
fd = fid->fd;
|
||||
eventmask = 0;
|
||||
if (FD_ISSET(fd, &ctx->rdLast))
|
||||
eventmask |= EV_READ;
|
||||
if (FD_ISSET(fd, &ctx->wrLast))
|
||||
eventmask |= EV_WRITE;
|
||||
if (FD_ISSET(fd, &ctx->exLast))
|
||||
eventmask |= EV_EXCEPT;
|
||||
eventmask &= fid->eventmask;
|
||||
if (eventmask != 0) {
|
||||
if ((eventmask & EV_READ) != 0) {
|
||||
FD_CLR(fd, &ctx->rdLast);
|
||||
ctx->fdCount--;
|
||||
}
|
||||
if ((eventmask & EV_WRITE) != 0) {
|
||||
FD_CLR(fd, &ctx->wrLast);
|
||||
ctx->fdCount--;
|
||||
}
|
||||
if ((eventmask & EV_EXCEPT) != 0) {
|
||||
FD_CLR(fd, &ctx->exLast);
|
||||
ctx->fdCount--;
|
||||
}
|
||||
OKNEW(new);
|
||||
new->type = File;
|
||||
new->u.file.this = fid;
|
||||
new->u.file.eventmask = eventmask;
|
||||
opaqueEv->opaque = new;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (ctx->fdCount < 0) {
|
||||
/*
|
||||
* select()'s count is off on a number of systems, and
|
||||
* can result in fdCount < 0.
|
||||
*/
|
||||
evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount);
|
||||
ctx->fdCount = 0;
|
||||
}
|
||||
|
||||
/* We get here if the caller deselect()'s an FD. Gag me with a goto. */
|
||||
goto again;
|
||||
}
|
||||
|
||||
int
|
||||
evDispatch(evContext opaqueCtx, evEvent opaqueEv) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evEvent_p *ev = opaqueEv.opaque;
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
void *func;
|
||||
struct timespec start_time;
|
||||
struct timespec interval;
|
||||
#endif
|
||||
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
if (ctx->debug > 0)
|
||||
start_time = evNowTime();
|
||||
#endif
|
||||
ctx->cur = ev;
|
||||
switch (ev->type) {
|
||||
case Accept: {
|
||||
evAccept *this = ev->u.accept.this;
|
||||
|
||||
evPrintf(ctx, 5,
|
||||
"Dispatch.Accept: fd %d -> %d, func %p, uap %p\n",
|
||||
this->conn->fd, this->fd,
|
||||
this->conn->func, this->conn->uap);
|
||||
errno = this->ioErrno;
|
||||
(this->conn->func)(opaqueCtx, this->conn->uap, this->fd,
|
||||
&this->la, this->lalen,
|
||||
&this->ra, this->ralen);
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
func = this->conn->func;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case File: {
|
||||
evFile *this = ev->u.file.this;
|
||||
int eventmask = ev->u.file.eventmask;
|
||||
|
||||
evPrintf(ctx, 5,
|
||||
"Dispatch.File: fd %d, mask 0x%x, func %p, uap %p\n",
|
||||
this->fd, this->eventmask, this->func, this->uap);
|
||||
(this->func)(opaqueCtx, this->uap, this->fd, eventmask);
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
func = this->func;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Stream: {
|
||||
evStream *this = ev->u.stream.this;
|
||||
|
||||
evPrintf(ctx, 5,
|
||||
"Dispatch.Stream: fd %d, func %p, uap %p\n",
|
||||
this->fd, this->func, this->uap);
|
||||
errno = this->ioErrno;
|
||||
(this->func)(opaqueCtx, this->uap, this->fd, this->ioDone);
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
func = this->func;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Timer: {
|
||||
evTimer *this = ev->u.timer.this;
|
||||
|
||||
evPrintf(ctx, 5, "Dispatch.Timer: func %p, uap %p\n",
|
||||
this->func, this->uap);
|
||||
(this->func)(opaqueCtx, this->uap, this->due, this->inter);
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
func = this->func;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Wait: {
|
||||
evWait *this = ev->u.wait.this;
|
||||
|
||||
evPrintf(ctx, 5,
|
||||
"Dispatch.Wait: tag %p, func %p, uap %p\n",
|
||||
this->tag, this->func, this->uap);
|
||||
(this->func)(opaqueCtx, this->uap, this->tag);
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
func = this->func;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Null: {
|
||||
/* No work. */
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
func = NULL;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
if (ctx->debug > 0) {
|
||||
interval = evSubTime(evNowTime(), start_time);
|
||||
/*
|
||||
* Complain if it took longer than 50 milliseconds.
|
||||
*
|
||||
* We call getuid() to make an easy to find mark in a kernel
|
||||
* trace.
|
||||
*/
|
||||
if (interval.tv_sec > 0 || interval.tv_nsec > 50000000)
|
||||
evPrintf(ctx, 1,
|
||||
"dispatch interval %u.%09u uid %d type %d func %p\n",
|
||||
interval.tv_sec, interval.tv_nsec,
|
||||
getuid(), ev->type, func);
|
||||
}
|
||||
#endif
|
||||
ctx->cur = NULL;
|
||||
evDrop(opaqueCtx, opaqueEv);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
evDrop(evContext opaqueCtx, evEvent opaqueEv) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
evEvent_p *ev = opaqueEv.opaque;
|
||||
|
||||
switch (ev->type) {
|
||||
case Accept: {
|
||||
FREE(ev->u.accept.this);
|
||||
break;
|
||||
}
|
||||
case File: {
|
||||
/* No work. */
|
||||
break;
|
||||
}
|
||||
case Stream: {
|
||||
evStreamID id;
|
||||
|
||||
id.opaque = ev->u.stream.this;
|
||||
(void) evCancelRW(opaqueCtx, id);
|
||||
break;
|
||||
}
|
||||
case Timer: {
|
||||
evTimer *this = ev->u.timer.this;
|
||||
evTimerID opaque;
|
||||
|
||||
/* Check to see whether the user func cleared the timer. */
|
||||
if (heap_element(ctx->timers, this->index) != this) {
|
||||
evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n");
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Timer is still there. Delete it if it has expired,
|
||||
* otherwise set it according to its next interval.
|
||||
*/
|
||||
if (this->inter.tv_sec == (time_t)0 &&
|
||||
this->inter.tv_nsec == 0L) {
|
||||
opaque.opaque = this;
|
||||
(void) evClearTimer(opaqueCtx, opaque);
|
||||
} else {
|
||||
opaque.opaque = this;
|
||||
(void) evResetTimer(opaqueCtx, opaque, this->func,
|
||||
this->uap,
|
||||
evAddTime((this->mode & EV_TMR_RATE) ?
|
||||
this->due :
|
||||
ctx->lastEventTime,
|
||||
this->inter),
|
||||
this->inter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Wait: {
|
||||
FREE(ev->u.wait.this);
|
||||
break;
|
||||
}
|
||||
case Null: {
|
||||
/* No work. */
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
FREE(ev);
|
||||
}
|
||||
|
||||
int
|
||||
evMainLoop(evContext opaqueCtx) {
|
||||
evEvent event;
|
||||
int x;
|
||||
|
||||
while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0)
|
||||
if ((x = evDispatch(opaqueCtx, event)) < 0)
|
||||
break;
|
||||
return (x);
|
||||
}
|
||||
|
||||
int
|
||||
evHighestFD(evContext opaqueCtx) {
|
||||
evContext_p *ctx = opaqueCtx.opaque;
|
||||
|
||||
return (ctx->highestFD);
|
||||
}
|
||||
|
||||
void
|
||||
evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (ctx->output != NULL && ctx->debug >= level) {
|
||||
vfprintf(ctx->output, fmt, ap);
|
||||
fflush(ctx->output);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int
|
||||
evSetOption(evContext *opaqueCtx, const char *option, int value) {
|
||||
/* evContext_p *ctx = opaqueCtx->opaque; */
|
||||
|
||||
UNUSED(opaqueCtx);
|
||||
UNUSED(value);
|
||||
#ifndef CLOCK_MONOTONIC
|
||||
UNUSED(option);
|
||||
#endif
|
||||
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
if (strcmp(option, "monotime") == 0) {
|
||||
if (opaqueCtx != NULL)
|
||||
errno = EINVAL;
|
||||
if (value == 0 || value == 1) {
|
||||
__evOptMonoTime = value;
|
||||
return (0);
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
evGetOption(evContext *opaqueCtx, const char *option, int *value) {
|
||||
/* evContext_p *ctx = opaqueCtx->opaque; */
|
||||
|
||||
UNUSED(opaqueCtx);
|
||||
#ifndef CLOCK_MONOTONIC
|
||||
UNUSED(value);
|
||||
UNUSED(option);
|
||||
#endif
|
||||
|
||||
#ifdef CLOCK_MONOTONIC
|
||||
if (strcmp(option, "monotime") == 0) {
|
||||
if (opaqueCtx != NULL)
|
||||
errno = EINVAL;
|
||||
*value = __evOptMonoTime;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifdef NEED_PSELECT
|
||||
/* XXX needs to move to the porting library. */
|
||||
static int
|
||||
pselect(int nfds, void *rfds, void *wfds, void *efds,
|
||||
struct timespec *tsp,
|
||||
const sigset_t *sigmask)
|
||||
{
|
||||
struct timeval tv, *tvp;
|
||||
sigset_t sigs;
|
||||
int n;
|
||||
|
||||
if (tsp) {
|
||||
tvp = &tv;
|
||||
tv = evTimeVal(*tsp);
|
||||
} else
|
||||
tvp = NULL;
|
||||
if (sigmask)
|
||||
sigprocmask(SIG_SETMASK, sigmask, &sigs);
|
||||
n = select(nfds, rfds, wfds, efds, tvp);
|
||||
if (sigmask)
|
||||
sigprocmask(SIG_SETMASK, &sigs, NULL);
|
||||
if (tsp)
|
||||
*tsp = evTimeSpec(tv);
|
||||
return (n);
|
||||
}
|
||||
#endif
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1995-1999 by Internet Software Consortium
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* eventlib_p.h - private interfaces for eventlib
|
||||
* vix 09sep95 [initial]
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _EVENTLIB_P_H
|
||||
#define _EVENTLIB_P_H
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#define EVENTLIB_DEBUG 1
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/heap.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/memcluster.h>
|
||||
|
||||
#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT)
|
||||
#define EV_ERR(e) return (errno = (e), -1)
|
||||
#define OK(x) if ((x) < 0) EV_ERR(errno); else (void)NULL
|
||||
|
||||
#define NEW(p) if (((p) = memget(sizeof *(p))) != NULL) \
|
||||
FILL(p); \
|
||||
else \
|
||||
(void)NULL;
|
||||
#define OKNEW(p) if (!((p) = memget(sizeof *(p)))) { \
|
||||
errno = ENOMEM; \
|
||||
return (-1); \
|
||||
} else \
|
||||
FILL(p)
|
||||
#define FREE(p) memput((p), sizeof *(p))
|
||||
|
||||
#if EVENTLIB_DEBUG
|
||||
#define FILL(p) memset((p), 0xF5, sizeof *(p))
|
||||
#else
|
||||
#define FILL(p)
|
||||
#endif
|
||||
|
||||
typedef struct evConn {
|
||||
evConnFunc func;
|
||||
void * uap;
|
||||
int fd;
|
||||
int flags;
|
||||
#define EV_CONN_LISTEN 0x0001 /* Connection is a listener. */
|
||||
#define EV_CONN_SELECTED 0x0002 /* evSelectFD(conn->file). */
|
||||
#define EV_CONN_BLOCK 0x0004 /* Listener fd was blocking. */
|
||||
evFileID file;
|
||||
struct evConn * prev;
|
||||
struct evConn * next;
|
||||
} evConn;
|
||||
|
||||
typedef struct evAccept {
|
||||
int fd;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in in;
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
struct sockaddr_un un;
|
||||
#endif
|
||||
} la;
|
||||
ISC_SOCKLEN_T lalen;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in in;
|
||||
#ifndef NO_SOCKADDR_UN
|
||||
struct sockaddr_un un;
|
||||
#endif
|
||||
} ra;
|
||||
ISC_SOCKLEN_T ralen;
|
||||
int ioErrno;
|
||||
evConn * conn;
|
||||
LINK(struct evAccept) link;
|
||||
} evAccept;
|
||||
|
||||
typedef struct evFile {
|
||||
evFileFunc func;
|
||||
void * uap;
|
||||
int fd;
|
||||
int eventmask;
|
||||
int preemptive;
|
||||
struct evFile * prev;
|
||||
struct evFile * next;
|
||||
struct evFile * fdprev;
|
||||
struct evFile * fdnext;
|
||||
} evFile;
|
||||
|
||||
typedef struct evStream {
|
||||
evStreamFunc func;
|
||||
void * uap;
|
||||
evFileID file;
|
||||
evTimerID timer;
|
||||
int flags;
|
||||
#define EV_STR_TIMEROK 0x0001 /* IFF timer valid. */
|
||||
int fd;
|
||||
struct iovec * iovOrig;
|
||||
int iovOrigCount;
|
||||
struct iovec * iovCur;
|
||||
int iovCurCount;
|
||||
int ioTotal;
|
||||
int ioDone;
|
||||
int ioErrno;
|
||||
struct evStream *prevDone, *nextDone;
|
||||
struct evStream *prev, *next;
|
||||
} evStream;
|
||||
|
||||
typedef struct evTimer {
|
||||
evTimerFunc func;
|
||||
void * uap;
|
||||
struct timespec due, inter;
|
||||
int index;
|
||||
int mode;
|
||||
#define EV_TMR_RATE 1
|
||||
} evTimer;
|
||||
|
||||
typedef struct evWait {
|
||||
evWaitFunc func;
|
||||
void * uap;
|
||||
const void * tag;
|
||||
struct evWait * next;
|
||||
} evWait;
|
||||
|
||||
typedef struct evWaitList {
|
||||
evWait * first;
|
||||
evWait * last;
|
||||
struct evWaitList * prev;
|
||||
struct evWaitList * next;
|
||||
} evWaitList;
|
||||
|
||||
typedef struct evEvent_p {
|
||||
enum { Accept, File, Stream, Timer, Wait, Free, Null } type;
|
||||
union {
|
||||
struct { evAccept *this; } accept;
|
||||
struct { evFile *this; int eventmask; } file;
|
||||
struct { evStream *this; } stream;
|
||||
struct { evTimer *this; } timer;
|
||||
struct { evWait *this; } wait;
|
||||
struct { struct evEvent_p *next; } free;
|
||||
struct { const void *placeholder; } null;
|
||||
} u;
|
||||
} evEvent_p;
|
||||
|
||||
typedef struct {
|
||||
/* Global. */
|
||||
const evEvent_p *cur;
|
||||
/* Debugging. */
|
||||
int debug;
|
||||
FILE *output;
|
||||
/* Connections. */
|
||||
evConn *conns;
|
||||
LIST(evAccept) accepts;
|
||||
/* Files. */
|
||||
evFile *files, *fdNext;
|
||||
fd_set rdLast, rdNext;
|
||||
fd_set wrLast, wrNext;
|
||||
fd_set exLast, exNext;
|
||||
fd_set nonblockBefore;
|
||||
int fdMax, fdCount, highestFD;
|
||||
evFile *fdTable[FD_SETSIZE];
|
||||
#ifdef EVENTLIB_TIME_CHECKS
|
||||
struct timespec lastSelectTime;
|
||||
int lastFdCount;
|
||||
#endif
|
||||
/* Streams. */
|
||||
evStream *streams;
|
||||
evStream *strDone, *strLast;
|
||||
/* Timers. */
|
||||
struct timespec lastEventTime;
|
||||
heap_context timers;
|
||||
/* Waits. */
|
||||
evWaitList *waitLists;
|
||||
evWaitList waitDone;
|
||||
} evContext_p;
|
||||
|
||||
/* eventlib.c */
|
||||
#define evPrintf __evPrintf
|
||||
void evPrintf(const evContext_p *ctx, int level, const char *fmt, ...)
|
||||
ISC_FORMAT_PRINTF(3, 4);
|
||||
|
||||
/* ev_timers.c */
|
||||
#define evCreateTimers __evCreateTimers
|
||||
heap_context evCreateTimers(const evContext_p *);
|
||||
#define evDestroyTimers __evDestroyTimers
|
||||
void evDestroyTimers(const evContext_p *);
|
||||
|
||||
/* ev_waits.c */
|
||||
#define evFreeWait __evFreeWait
|
||||
evWait *evFreeWait(evContext_p *ctx, evWait *old);
|
||||
|
||||
/* Global options */
|
||||
extern int __evOptMonoTime;
|
||||
|
||||
#endif /*_EVENTLIB_P_H*/
|
||||
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1997,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Heap implementation of priority queues adapted from the following:
|
||||
*
|
||||
* _Introduction to Algorithms_, Cormen, Leiserson, and Rivest,
|
||||
* MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7.
|
||||
*
|
||||
* _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988,
|
||||
* ISBN 0-201-06673-4, chapter 11.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include <isc/heap.h>
|
||||
|
||||
/*
|
||||
* Note: to make heap_parent and heap_left easy to compute, the first
|
||||
* element of the heap array is not used; i.e. heap subscripts are 1-based,
|
||||
* not 0-based.
|
||||
*/
|
||||
#define heap_parent(i) ((i) >> 1)
|
||||
#define heap_left(i) ((i) << 1)
|
||||
|
||||
#define ARRAY_SIZE_INCREMENT 512
|
||||
|
||||
heap_context
|
||||
heap_new(heap_higher_priority_func higher_priority, heap_index_func index,
|
||||
int array_size_increment) {
|
||||
heap_context ctx;
|
||||
|
||||
ctx = (heap_context)malloc(sizeof (struct heap_context));
|
||||
if (ctx == NULL || higher_priority == NULL)
|
||||
return (NULL);
|
||||
ctx->array_size = 0;
|
||||
if (array_size_increment == 0)
|
||||
ctx->array_size_increment = ARRAY_SIZE_INCREMENT;
|
||||
else
|
||||
ctx->array_size_increment = array_size_increment;
|
||||
ctx->heap_size = 0;
|
||||
ctx->heap = NULL;
|
||||
ctx->higher_priority = higher_priority;
|
||||
ctx->index = index;
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
int
|
||||
heap_free(heap_context ctx) {
|
||||
if (ctx == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (ctx->heap != NULL)
|
||||
free(ctx->heap);
|
||||
free(ctx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
heap_resize(heap_context ctx) {
|
||||
void **new_heap;
|
||||
|
||||
ctx->array_size += ctx->array_size_increment;
|
||||
new_heap = (void **)realloc(ctx->heap,
|
||||
(ctx->array_size) * (sizeof (void *)));
|
||||
if (new_heap == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
ctx->heap = new_heap;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
float_up(heap_context ctx, int i, void *elt) {
|
||||
int p;
|
||||
|
||||
for ( p = heap_parent(i);
|
||||
i > 1 && ctx->higher_priority(elt, ctx->heap[p]);
|
||||
i = p, p = heap_parent(i) ) {
|
||||
ctx->heap[i] = ctx->heap[p];
|
||||
if (ctx->index != NULL)
|
||||
(ctx->index)(ctx->heap[i], i);
|
||||
}
|
||||
ctx->heap[i] = elt;
|
||||
if (ctx->index != NULL)
|
||||
(ctx->index)(ctx->heap[i], i);
|
||||
}
|
||||
|
||||
static void
|
||||
sink_down(heap_context ctx, int i, void *elt) {
|
||||
int j, size, half_size;
|
||||
|
||||
size = ctx->heap_size;
|
||||
half_size = size / 2;
|
||||
while (i <= half_size) {
|
||||
/* find smallest of the (at most) two children */
|
||||
j = heap_left(i);
|
||||
if (j < size && ctx->higher_priority(ctx->heap[j+1],
|
||||
ctx->heap[j]))
|
||||
j++;
|
||||
if (ctx->higher_priority(elt, ctx->heap[j]))
|
||||
break;
|
||||
ctx->heap[i] = ctx->heap[j];
|
||||
if (ctx->index != NULL)
|
||||
(ctx->index)(ctx->heap[i], i);
|
||||
i = j;
|
||||
}
|
||||
ctx->heap[i] = elt;
|
||||
if (ctx->index != NULL)
|
||||
(ctx->index)(ctx->heap[i], i);
|
||||
}
|
||||
|
||||
int
|
||||
heap_insert(heap_context ctx, void *elt) {
|
||||
int i;
|
||||
|
||||
if (ctx == NULL || elt == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
i = ++ctx->heap_size;
|
||||
if (ctx->heap_size >= ctx->array_size && heap_resize(ctx) < 0)
|
||||
return (-1);
|
||||
|
||||
float_up(ctx, i, elt);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
heap_delete(heap_context ctx, int i) {
|
||||
void *elt;
|
||||
int less;
|
||||
|
||||
if (ctx == NULL || i < 1 || i > ctx->heap_size) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (i == ctx->heap_size) {
|
||||
ctx->heap_size--;
|
||||
} else {
|
||||
elt = ctx->heap[ctx->heap_size--];
|
||||
less = ctx->higher_priority(elt, ctx->heap[i]);
|
||||
ctx->heap[i] = elt;
|
||||
if (less)
|
||||
float_up(ctx, i, ctx->heap[i]);
|
||||
else
|
||||
sink_down(ctx, i, ctx->heap[i]);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
heap_increased(heap_context ctx, int i) {
|
||||
if (ctx == NULL || i < 1 || i > ctx->heap_size) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
float_up(ctx, i, ctx->heap[i]);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
heap_decreased(heap_context ctx, int i) {
|
||||
if (ctx == NULL || i < 1 || i > ctx->heap_size) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sink_down(ctx, i, ctx->heap[i]);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void *
|
||||
heap_element(heap_context ctx, int i) {
|
||||
if (ctx == NULL || i < 1 || i > ctx->heap_size) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (ctx->heap[i]);
|
||||
}
|
||||
|
||||
int
|
||||
heap_for_each(heap_context ctx, heap_for_each_func action, void *uap) {
|
||||
int i;
|
||||
|
||||
if (ctx == NULL || action == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i = 1; i <= ctx->heap_size; i++)
|
||||
(action)(ctx->heap[i], uap);
|
||||
return (0);
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 2001 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <port_before.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <isc/misc.h>
|
||||
#include <port_after.h>
|
||||
|
||||
static const char hex[17] = "0123456789abcdef";
|
||||
|
||||
int
|
||||
isc_gethexstring(unsigned char *buf, size_t len, int count, FILE *fp,
|
||||
int *multiline)
|
||||
{
|
||||
int c, n;
|
||||
unsigned char x;
|
||||
char *s;
|
||||
int result = count;
|
||||
|
||||
x = 0; /* silence compiler */
|
||||
n = 0;
|
||||
while (count > 0) {
|
||||
c = fgetc(fp);
|
||||
|
||||
if ((c == EOF) ||
|
||||
(c == '\n' && !*multiline) ||
|
||||
(c == '(' && *multiline) ||
|
||||
(c == ')' && !*multiline))
|
||||
goto formerr;
|
||||
/* comment */
|
||||
if (c == ';') {
|
||||
while ((c = fgetc(fp)) != EOF && c != '\n')
|
||||
/* empty */
|
||||
if (c == '\n' && *multiline)
|
||||
continue;
|
||||
goto formerr;
|
||||
}
|
||||
/* white space */
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
continue;
|
||||
/* multiline */
|
||||
if ('(' == c || c == ')') {
|
||||
*multiline = (c == '(' /*)*/);
|
||||
continue;
|
||||
}
|
||||
if ((s = strchr(hex, tolower(c))) == NULL)
|
||||
goto formerr;
|
||||
x = (x<<4) | (s - hex);
|
||||
if (++n == 2) {
|
||||
if (len > 0U) {
|
||||
*buf++ = x;
|
||||
len--;
|
||||
} else
|
||||
result = -1;
|
||||
count--;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
|
||||
formerr:
|
||||
if (c == '\n')
|
||||
ungetc(c, fp);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
isc_puthexstring(FILE *fp, const unsigned char *buf, size_t buflen,
|
||||
size_t len1, size_t len2, const char *sep)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
if (len1 < 4U)
|
||||
len1 = 4;
|
||||
if (len2 < 4U)
|
||||
len2 = 4;
|
||||
while (buflen > 0U) {
|
||||
fputc(hex[(buf[0]>>4)&0xf], fp);
|
||||
fputc(hex[buf[0]&0xf], fp);
|
||||
i += 2;
|
||||
buflen--;
|
||||
buf++;
|
||||
if (i >= len1 && sep != NULL) {
|
||||
fputs(sep, fp);
|
||||
i = 0;
|
||||
len1 = len2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc_tohex(const unsigned char *buf, size_t buflen, char *t) {
|
||||
while (buflen > 0U) {
|
||||
*t++ = hex[(buf[0]>>4)&0xf];
|
||||
*t++ = hex[buf[0]&0xf];
|
||||
buf++;
|
||||
buflen--;
|
||||
}
|
||||
*t = '\0';
|
||||
}
|
||||
@@ -1,720 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <isc/logging.h>
|
||||
#include <isc/memcluster.h>
|
||||
#include <isc/misc.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef VSPRINTF_CHAR
|
||||
# define VSPRINTF(x) strlen(vsprintf/**/x)
|
||||
#else
|
||||
# define VSPRINTF(x) ((size_t)vsprintf x)
|
||||
#endif
|
||||
|
||||
#include "logging_p.h"
|
||||
|
||||
static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE,
|
||||
LOG_WARNING, LOG_ERR, LOG_CRIT };
|
||||
|
||||
static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
static const char *level_text[] = {
|
||||
"info: ", "notice: ", "warning: ", "error: ", "critical: "
|
||||
};
|
||||
|
||||
static void
|
||||
version_rename(log_channel chan) {
|
||||
unsigned int ver;
|
||||
char old_name[PATH_MAX+1];
|
||||
char new_name[PATH_MAX+1];
|
||||
|
||||
ver = chan->out.file.versions;
|
||||
if (ver < 1)
|
||||
return;
|
||||
if (ver > LOG_MAX_VERSIONS)
|
||||
ver = LOG_MAX_VERSIONS;
|
||||
/*
|
||||
* Need to have room for '.nn' (XXX assumes LOG_MAX_VERSIONS < 100)
|
||||
*/
|
||||
if (strlen(chan->out.file.name) > (size_t)(PATH_MAX-3))
|
||||
return;
|
||||
for (ver--; ver > 0; ver--) {
|
||||
sprintf(old_name, "%s.%d", chan->out.file.name, ver-1);
|
||||
sprintf(new_name, "%s.%d", chan->out.file.name, ver);
|
||||
(void)isc_movefile(old_name, new_name);
|
||||
}
|
||||
sprintf(new_name, "%s.0", chan->out.file.name);
|
||||
(void)isc_movefile(chan->out.file.name, new_name);
|
||||
}
|
||||
|
||||
FILE *
|
||||
log_open_stream(log_channel chan) {
|
||||
FILE *stream;
|
||||
int fd, flags;
|
||||
struct stat sb;
|
||||
int regular;
|
||||
|
||||
if (chan == NULL || chan->type != log_file) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't open already open streams
|
||||
*/
|
||||
if (chan->out.file.stream != NULL)
|
||||
return (chan->out.file.stream);
|
||||
|
||||
if (stat(chan->out.file.name, &sb) < 0) {
|
||||
if (errno != ENOENT) {
|
||||
syslog(LOG_ERR,
|
||||
"log_open_stream: stat of %s failed: %s",
|
||||
chan->out.file.name, strerror(errno));
|
||||
chan->flags |= LOG_CHANNEL_BROKEN;
|
||||
return (NULL);
|
||||
}
|
||||
regular = 1;
|
||||
} else
|
||||
regular = (sb.st_mode & S_IFREG);
|
||||
|
||||
if (chan->out.file.versions) {
|
||||
if (!regular) {
|
||||
syslog(LOG_ERR,
|
||||
"log_open_stream: want versions but %s isn't a regular file",
|
||||
chan->out.file.name);
|
||||
chan->flags |= LOG_CHANNEL_BROKEN;
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
flags = O_WRONLY|O_CREAT|O_APPEND;
|
||||
|
||||
if ((chan->flags & LOG_TRUNCATE) != 0) {
|
||||
if (regular) {
|
||||
(void)unlink(chan->out.file.name);
|
||||
flags |= O_EXCL;
|
||||
} else {
|
||||
syslog(LOG_ERR,
|
||||
"log_open_stream: want truncation but %s isn't a regular file",
|
||||
chan->out.file.name);
|
||||
chan->flags |= LOG_CHANNEL_BROKEN;
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
fd = open(chan->out.file.name, flags,
|
||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
||||
if (fd < 0) {
|
||||
syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s",
|
||||
chan->out.file.name, strerror(errno));
|
||||
chan->flags |= LOG_CHANNEL_BROKEN;
|
||||
return (NULL);
|
||||
}
|
||||
stream = fdopen(fd, "a");
|
||||
if (stream == NULL) {
|
||||
syslog(LOG_ERR, "log_open_stream: fdopen() failed");
|
||||
chan->flags |= LOG_CHANNEL_BROKEN;
|
||||
return (NULL);
|
||||
}
|
||||
(void) fchown(fd, chan->out.file.owner, chan->out.file.group);
|
||||
|
||||
chan->out.file.stream = stream;
|
||||
return (stream);
|
||||
}
|
||||
|
||||
int
|
||||
log_close_stream(log_channel chan) {
|
||||
FILE *stream;
|
||||
|
||||
if (chan == NULL || chan->type != log_file) {
|
||||
errno = EINVAL;
|
||||
return (0);
|
||||
}
|
||||
stream = chan->out.file.stream;
|
||||
chan->out.file.stream = NULL;
|
||||
if (stream != NULL && fclose(stream) == EOF)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
log_close_debug_channels(log_context lc) {
|
||||
log_channel_list lcl;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < lc->num_categories; i++)
|
||||
for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl->next)
|
||||
if (lcl->channel->type == log_file &&
|
||||
lcl->channel->out.file.stream != NULL &&
|
||||
lcl->channel->flags & LOG_REQUIRE_DEBUG)
|
||||
(void)log_close_stream(lcl->channel);
|
||||
}
|
||||
|
||||
FILE *
|
||||
log_get_stream(log_channel chan) {
|
||||
if (chan == NULL || chan->type != log_file) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
return (chan->out.file.stream);
|
||||
}
|
||||
|
||||
char *
|
||||
log_get_filename(log_channel chan) {
|
||||
if (chan == NULL || chan->type != log_file) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
return (chan->out.file.name);
|
||||
}
|
||||
|
||||
int
|
||||
log_check_channel(log_context lc, int level, log_channel chan) {
|
||||
int debugging, chan_level;
|
||||
|
||||
REQUIRE(lc != NULL);
|
||||
|
||||
debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0);
|
||||
|
||||
/*
|
||||
* If not debugging, short circuit debugging messages very early.
|
||||
*/
|
||||
if (level > 0 && !debugging)
|
||||
return (0);
|
||||
|
||||
if ((chan->flags & (LOG_CHANNEL_BROKEN|LOG_CHANNEL_OFF)) != 0)
|
||||
return (0);
|
||||
|
||||
/* Some channels only log when debugging is on. */
|
||||
if ((chan->flags & LOG_REQUIRE_DEBUG) && !debugging)
|
||||
return (0);
|
||||
|
||||
/* Some channels use the global level. */
|
||||
if ((chan->flags & LOG_USE_CONTEXT_LEVEL) != 0) {
|
||||
chan_level = lc->level;
|
||||
} else
|
||||
chan_level = chan->level;
|
||||
|
||||
if (level > chan_level)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
log_check(log_context lc, int category, int level) {
|
||||
log_channel_list lcl;
|
||||
int debugging;
|
||||
|
||||
REQUIRE(lc != NULL);
|
||||
|
||||
debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0);
|
||||
|
||||
/*
|
||||
* If not debugging, short circuit debugging messages very early.
|
||||
*/
|
||||
if (level > 0 && !debugging)
|
||||
return (0);
|
||||
|
||||
if (category < 0 || category > lc->num_categories)
|
||||
category = 0; /* use default */
|
||||
lcl = lc->categories[category];
|
||||
if (lcl == NULL) {
|
||||
category = 0;
|
||||
lcl = lc->categories[0];
|
||||
}
|
||||
|
||||
for ( /* nothing */; lcl != NULL; lcl = lcl->next) {
|
||||
if (log_check_channel(lc, level, lcl->channel))
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
log_vwrite(log_context lc, int category, int level, const char *format,
|
||||
va_list args) {
|
||||
log_channel_list lcl;
|
||||
int pri, debugging, did_vsprintf = 0;
|
||||
int original_category;
|
||||
FILE *stream;
|
||||
log_channel chan;
|
||||
struct timeval tv;
|
||||
struct tm *local_tm;
|
||||
#ifdef HAVE_TIME_R
|
||||
struct tm tm_tmp;
|
||||
#endif
|
||||
time_t tt;
|
||||
const char *category_name;
|
||||
const char *level_str;
|
||||
char time_buf[256];
|
||||
char level_buf[256];
|
||||
|
||||
REQUIRE(lc != NULL);
|
||||
|
||||
debugging = (lc->flags & LOG_OPTION_DEBUG);
|
||||
|
||||
/*
|
||||
* If not debugging, short circuit debugging messages very early.
|
||||
*/
|
||||
if (level > 0 && !debugging)
|
||||
return;
|
||||
|
||||
if (category < 0 || category > lc->num_categories)
|
||||
category = 0; /* use default */
|
||||
original_category = category;
|
||||
lcl = lc->categories[category];
|
||||
if (lcl == NULL) {
|
||||
category = 0;
|
||||
lcl = lc->categories[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current time and format it.
|
||||
*/
|
||||
time_buf[0]='\0';
|
||||
if (gettimeofday(&tv, NULL) < 0) {
|
||||
syslog(LOG_INFO, "gettimeofday failed in log_vwrite()");
|
||||
} else {
|
||||
tt = tv.tv_sec;
|
||||
#ifdef HAVE_TIME_R
|
||||
local_tm = localtime_r(&tt, &tm_tmp);
|
||||
#else
|
||||
local_tm = localtime(&tt);
|
||||
#endif
|
||||
if (local_tm != NULL) {
|
||||
sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ",
|
||||
local_tm->tm_mday, months[local_tm->tm_mon],
|
||||
local_tm->tm_year+1900, local_tm->tm_hour,
|
||||
local_tm->tm_min, local_tm->tm_sec,
|
||||
(long)tv.tv_usec/1000);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a string representation of the current category and level
|
||||
*/
|
||||
|
||||
if (lc->category_names != NULL &&
|
||||
lc->category_names[original_category] != NULL)
|
||||
category_name = lc->category_names[original_category];
|
||||
else
|
||||
category_name = "";
|
||||
|
||||
if (level >= log_critical) {
|
||||
if (level >= 0) {
|
||||
sprintf(level_buf, "debug %d: ", level);
|
||||
level_str = level_buf;
|
||||
} else
|
||||
level_str = level_text[-level-1];
|
||||
} else {
|
||||
sprintf(level_buf, "level %d: ", level);
|
||||
level_str = level_buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the message to channels.
|
||||
*/
|
||||
for ( /* nothing */; lcl != NULL; lcl = lcl->next) {
|
||||
chan = lcl->channel;
|
||||
|
||||
if (!log_check_channel(lc, level, chan))
|
||||
continue;
|
||||
|
||||
if (!did_vsprintf) {
|
||||
if (VSPRINTF((lc->buffer, format, args)) >
|
||||
(size_t)LOG_BUFFER_SIZE) {
|
||||
syslog(LOG_CRIT,
|
||||
"memory overrun in log_vwrite()");
|
||||
exit(1);
|
||||
}
|
||||
did_vsprintf = 1;
|
||||
}
|
||||
|
||||
switch (chan->type) {
|
||||
case log_syslog:
|
||||
if (level >= log_critical)
|
||||
pri = (level >= 0) ? 0 : -level;
|
||||
else
|
||||
pri = -log_critical;
|
||||
syslog(chan->out.facility|syslog_priority[pri],
|
||||
"%s%s%s%s",
|
||||
(chan->flags & LOG_TIMESTAMP) ? time_buf : "",
|
||||
(chan->flags & LOG_PRINT_CATEGORY) ?
|
||||
category_name : "",
|
||||
(chan->flags & LOG_PRINT_LEVEL) ?
|
||||
level_str : "",
|
||||
lc->buffer);
|
||||
break;
|
||||
case log_file:
|
||||
stream = chan->out.file.stream;
|
||||
if (stream == NULL) {
|
||||
stream = log_open_stream(chan);
|
||||
if (stream == NULL)
|
||||
break;
|
||||
}
|
||||
if (chan->out.file.max_size != ULONG_MAX) {
|
||||
long pos;
|
||||
|
||||
pos = ftell(stream);
|
||||
if (pos >= 0 &&
|
||||
(unsigned long)pos >
|
||||
chan->out.file.max_size) {
|
||||
/*
|
||||
* try to roll over the log files,
|
||||
* ignoring all all return codes
|
||||
* except the open (we don't want
|
||||
* to write any more anyway)
|
||||
*/
|
||||
log_close_stream(chan);
|
||||
version_rename(chan);
|
||||
stream = log_open_stream(chan);
|
||||
if (stream == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stream, "%s%s%s%s\n",
|
||||
(chan->flags & LOG_TIMESTAMP) ? time_buf : "",
|
||||
(chan->flags & LOG_PRINT_CATEGORY) ?
|
||||
category_name : "",
|
||||
(chan->flags & LOG_PRINT_LEVEL) ?
|
||||
level_str : "",
|
||||
lc->buffer);
|
||||
fflush(stream);
|
||||
break;
|
||||
case log_null:
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR,
|
||||
"unknown channel type in log_vwrite()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
log_write(log_context lc, int category, int level, const char *format, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
log_vwrite(lc, category, level, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to create, set, or destroy contexts
|
||||
*/
|
||||
|
||||
int
|
||||
log_new_context(int num_categories, char **category_names, log_context *lc) {
|
||||
log_context nlc;
|
||||
|
||||
nlc = memget(sizeof (struct log_context));
|
||||
if (nlc == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
nlc->num_categories = num_categories;
|
||||
nlc->category_names = category_names;
|
||||
nlc->categories = memget(num_categories * sizeof (log_channel_list));
|
||||
if (nlc->categories == NULL) {
|
||||
memput(nlc, sizeof (struct log_context));
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
memset(nlc->categories, '\0',
|
||||
num_categories * sizeof (log_channel_list));
|
||||
nlc->flags = 0U;
|
||||
nlc->level = 0;
|
||||
*lc = nlc;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
log_free_context(log_context lc) {
|
||||
log_channel_list lcl, lcl_next;
|
||||
log_channel chan;
|
||||
int i;
|
||||
|
||||
REQUIRE(lc != NULL);
|
||||
|
||||
for (i = 0; i < lc->num_categories; i++)
|
||||
for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl_next) {
|
||||
lcl_next = lcl->next;
|
||||
chan = lcl->channel;
|
||||
(void)log_free_channel(chan);
|
||||
memput(lcl, sizeof (struct log_channel_list));
|
||||
}
|
||||
memput(lc->categories,
|
||||
lc->num_categories * sizeof (log_channel_list));
|
||||
memput(lc, sizeof (struct log_context));
|
||||
}
|
||||
|
||||
int
|
||||
log_add_channel(log_context lc, int category, log_channel chan) {
|
||||
log_channel_list lcl;
|
||||
|
||||
if (lc == NULL || category < 0 || category >= lc->num_categories) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
lcl = memget(sizeof (struct log_channel_list));
|
||||
if (lcl == NULL) {
|
||||
errno = ENOMEM;
|
||||
return(-1);
|
||||
}
|
||||
lcl->channel = chan;
|
||||
lcl->next = lc->categories[category];
|
||||
lc->categories[category] = lcl;
|
||||
chan->references++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
log_remove_channel(log_context lc, int category, log_channel chan) {
|
||||
log_channel_list lcl, prev_lcl, next_lcl;
|
||||
int found = 0;
|
||||
|
||||
if (lc == NULL || category < 0 || category >= lc->num_categories) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (prev_lcl = NULL, lcl = lc->categories[category];
|
||||
lcl != NULL;
|
||||
lcl = next_lcl) {
|
||||
next_lcl = lcl->next;
|
||||
if (lcl->channel == chan) {
|
||||
log_free_channel(chan);
|
||||
if (prev_lcl != NULL)
|
||||
prev_lcl->next = next_lcl;
|
||||
else
|
||||
lc->categories[category] = next_lcl;
|
||||
memput(lcl, sizeof (struct log_channel_list));
|
||||
/*
|
||||
* We just set found instead of returning because
|
||||
* the channel might be on the list more than once.
|
||||
*/
|
||||
found = 1;
|
||||
} else
|
||||
prev_lcl = lcl;
|
||||
}
|
||||
if (!found) {
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
log_option(log_context lc, int option, int value) {
|
||||
if (lc == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
switch (option) {
|
||||
case LOG_OPTION_DEBUG:
|
||||
if (value)
|
||||
lc->flags |= option;
|
||||
else
|
||||
lc->flags &= ~option;
|
||||
break;
|
||||
case LOG_OPTION_LEVEL:
|
||||
lc->level = value;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
log_category_is_active(log_context lc, int category) {
|
||||
if (lc == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if (category >= 0 && category < lc->num_categories &&
|
||||
lc->categories[category] != NULL)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
log_channel
|
||||
log_new_syslog_channel(unsigned int flags, int level, int facility) {
|
||||
log_channel chan;
|
||||
|
||||
chan = memget(sizeof (struct log_channel));
|
||||
if (chan == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
chan->type = log_syslog;
|
||||
chan->flags = flags;
|
||||
chan->level = level;
|
||||
chan->out.facility = facility;
|
||||
chan->references = 0;
|
||||
return (chan);
|
||||
}
|
||||
|
||||
log_channel
|
||||
log_new_file_channel(unsigned int flags, int level,
|
||||
const char *name, FILE *stream, unsigned int versions,
|
||||
unsigned long max_size) {
|
||||
log_channel chan;
|
||||
|
||||
chan = memget(sizeof (struct log_channel));
|
||||
if (chan == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
chan->type = log_file;
|
||||
chan->flags = flags;
|
||||
chan->level = level;
|
||||
if (name != NULL) {
|
||||
size_t len;
|
||||
|
||||
len = strlen(name);
|
||||
/*
|
||||
* Quantize length to a multiple of 256. There's space for the
|
||||
* NUL, since if len is a multiple of 256, the size chosen will
|
||||
* be the next multiple.
|
||||
*/
|
||||
chan->out.file.name_size = ((len / 256) + 1) * 256;
|
||||
chan->out.file.name = memget(chan->out.file.name_size);
|
||||
if (chan->out.file.name == NULL) {
|
||||
memput(chan, sizeof (struct log_channel));
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
/* This is safe. */
|
||||
strcpy(chan->out.file.name, name);
|
||||
} else {
|
||||
chan->out.file.name_size = 0;
|
||||
chan->out.file.name = NULL;
|
||||
}
|
||||
chan->out.file.stream = stream;
|
||||
chan->out.file.versions = versions;
|
||||
chan->out.file.max_size = max_size;
|
||||
chan->out.file.owner = getuid();
|
||||
chan->out.file.group = getgid();
|
||||
chan->references = 0;
|
||||
return (chan);
|
||||
}
|
||||
|
||||
int
|
||||
log_set_file_owner(log_channel chan, uid_t owner, gid_t group) {
|
||||
if (chan->type != log_file) {
|
||||
errno = EBADF;
|
||||
return (-1);
|
||||
}
|
||||
chan->out.file.owner = owner;
|
||||
chan->out.file.group = group;
|
||||
return (0);
|
||||
}
|
||||
|
||||
log_channel
|
||||
log_new_null_channel() {
|
||||
log_channel chan;
|
||||
|
||||
chan = memget(sizeof (struct log_channel));
|
||||
if (chan == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
chan->type = log_null;
|
||||
chan->flags = LOG_CHANNEL_OFF;
|
||||
chan->level = log_info;
|
||||
chan->references = 0;
|
||||
return (chan);
|
||||
}
|
||||
|
||||
int
|
||||
log_inc_references(log_channel chan) {
|
||||
if (chan == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
chan->references++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
log_dec_references(log_channel chan) {
|
||||
if (chan == NULL || chan->references <= 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
chan->references--;
|
||||
return (0);
|
||||
}
|
||||
|
||||
log_channel_type
|
||||
log_get_channel_type(log_channel chan) {
|
||||
REQUIRE(chan != NULL);
|
||||
|
||||
return (chan->type);
|
||||
}
|
||||
|
||||
int
|
||||
log_free_channel(log_channel chan) {
|
||||
if (chan == NULL || chan->references <= 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
chan->references--;
|
||||
if (chan->references == 0) {
|
||||
if (chan->type == log_file) {
|
||||
if ((chan->flags & LOG_CLOSE_STREAM) &&
|
||||
chan->out.file.stream != NULL)
|
||||
(void)fclose(chan->out.file.stream);
|
||||
if (chan->out.file.name != NULL)
|
||||
memput(chan->out.file.name,
|
||||
chan->out.file.name_size);
|
||||
}
|
||||
memput(chan, sizeof (struct log_channel));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LOGGING_P_H
|
||||
#define LOGGING_P_H
|
||||
|
||||
typedef struct log_file_desc {
|
||||
char *name;
|
||||
size_t name_size;
|
||||
FILE *stream;
|
||||
unsigned int versions;
|
||||
unsigned long max_size;
|
||||
uid_t owner;
|
||||
gid_t group;
|
||||
} log_file_desc;
|
||||
|
||||
typedef union log_output {
|
||||
int facility;
|
||||
log_file_desc file;
|
||||
} log_output;
|
||||
|
||||
struct log_channel {
|
||||
int level; /* don't log messages > level */
|
||||
log_channel_type type;
|
||||
log_output out;
|
||||
unsigned int flags;
|
||||
int references;
|
||||
};
|
||||
|
||||
typedef struct log_channel_list {
|
||||
log_channel channel;
|
||||
struct log_channel_list *next;
|
||||
} *log_channel_list;
|
||||
|
||||
#define LOG_BUFFER_SIZE 20480
|
||||
|
||||
struct log_context {
|
||||
int num_categories;
|
||||
char **category_names;
|
||||
log_channel_list *categories;
|
||||
int flags;
|
||||
int level;
|
||||
char buffer[LOG_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
#endif /* !LOGGING_P_H */
|
||||
@@ -1,545 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 1997,1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/* When this symbol is defined allocations via memget are made slightly
|
||||
bigger and some debugging info stuck before and after the region given
|
||||
back to the caller. */
|
||||
/* #define DEBUGGING_MEMCLUSTER */
|
||||
#define MEMCLUSTER_ATEND
|
||||
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <isc/assertions.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
#ifndef DEBUGGING_MEMCLUSTER
|
||||
#define DEBUGGING_MEMCLUSTER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DEF_MAX_SIZE 1100
|
||||
#define DEF_MEM_TARGET 4096
|
||||
|
||||
typedef u_int32_t fence_t;
|
||||
|
||||
typedef struct {
|
||||
void * next;
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
#if defined(MEMCLUSTER_RECORD)
|
||||
const char * file;
|
||||
int line;
|
||||
#endif
|
||||
size_t size;
|
||||
fence_t fencepost;
|
||||
#endif
|
||||
} memcluster_element;
|
||||
|
||||
#define SMALL_SIZE_LIMIT sizeof(memcluster_element)
|
||||
#define P_SIZE sizeof(void *)
|
||||
#define FRONT_FENCEPOST 0xfebafeba
|
||||
#define BACK_FENCEPOST 0xabefabef
|
||||
#define FENCEPOST_SIZE 4
|
||||
|
||||
#ifndef MEMCLUSTER_LITTLE_MALLOC
|
||||
#define MEMCLUSTER_BIG_MALLOC 1
|
||||
#define NUM_BASIC_BLOCKS 64
|
||||
#endif
|
||||
|
||||
struct stats {
|
||||
u_long gets;
|
||||
u_long totalgets;
|
||||
u_long blocks;
|
||||
u_long freefrags;
|
||||
};
|
||||
|
||||
/* Private data. */
|
||||
|
||||
static size_t max_size;
|
||||
static size_t mem_target;
|
||||
static size_t mem_target_half;
|
||||
static size_t mem_target_fudge;
|
||||
static memcluster_element ** freelists;
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
static memcluster_element ** activelists;
|
||||
#endif
|
||||
#ifdef MEMCLUSTER_BIG_MALLOC
|
||||
static memcluster_element * basic_blocks;
|
||||
#endif
|
||||
static struct stats * stats;
|
||||
|
||||
/* Forward. */
|
||||
|
||||
static size_t quantize(size_t);
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
static void check(unsigned char *, int, size_t);
|
||||
#endif
|
||||
|
||||
/* Public. */
|
||||
|
||||
int
|
||||
meminit(size_t init_max_size, size_t target_size) {
|
||||
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
INSIST(sizeof(fence_t) == FENCEPOST_SIZE);
|
||||
#endif
|
||||
if (freelists != NULL) {
|
||||
errno = EEXIST;
|
||||
return (-1);
|
||||
}
|
||||
if (init_max_size == 0U)
|
||||
max_size = DEF_MAX_SIZE;
|
||||
else
|
||||
max_size = init_max_size;
|
||||
if (target_size == 0U)
|
||||
mem_target = DEF_MEM_TARGET;
|
||||
else
|
||||
mem_target = target_size;
|
||||
mem_target_half = mem_target / 2;
|
||||
mem_target_fudge = mem_target + mem_target / 4;
|
||||
freelists = malloc(max_size * sizeof (memcluster_element *));
|
||||
stats = malloc((max_size+1) * sizeof (struct stats));
|
||||
if (freelists == NULL || stats == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
memset(freelists, 0,
|
||||
max_size * sizeof (memcluster_element *));
|
||||
memset(stats, 0, (max_size + 1) * sizeof (struct stats));
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
activelists = malloc((max_size + 1) * sizeof (memcluster_element *));
|
||||
if (activelists == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
memset(activelists, 0,
|
||||
(max_size + 1) * sizeof (memcluster_element *));
|
||||
#endif
|
||||
#ifdef MEMCLUSTER_BIG_MALLOC
|
||||
basic_blocks = NULL;
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
void *
|
||||
__memget(size_t size) {
|
||||
return (__memget_record(size, NULL, 0));
|
||||
}
|
||||
|
||||
void *
|
||||
__memget_record(size_t size, const char *file, int line) {
|
||||
size_t new_size = quantize(size);
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
memcluster_element *e;
|
||||
char *p;
|
||||
fence_t fp = BACK_FENCEPOST;
|
||||
#endif
|
||||
void *ret;
|
||||
|
||||
#if !defined(MEMCLUSTER_RECORD)
|
||||
UNUSED(file);
|
||||
UNUSED(line);
|
||||
#endif
|
||||
if (freelists == NULL)
|
||||
if (meminit(0, 0) == -1)
|
||||
return (NULL);
|
||||
if (size == 0U) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (size >= max_size || new_size >= max_size) {
|
||||
/* memget() was called on something beyond our upper limit. */
|
||||
stats[max_size].gets++;
|
||||
stats[max_size].totalgets++;
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
e = malloc(new_size);
|
||||
if (e == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
e->next = NULL;
|
||||
e->size = size;
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
e->file = file;
|
||||
e->line = line;
|
||||
e->next = activelists[max_size];
|
||||
activelists[max_size] = e;
|
||||
#endif
|
||||
e->fencepost = FRONT_FENCEPOST;
|
||||
p = (char *)e + sizeof *e + size;
|
||||
memcpy(p, &fp, sizeof fp);
|
||||
return ((char *)e + sizeof *e);
|
||||
#else
|
||||
return (malloc(size));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are no blocks in the free list for this size, get a chunk
|
||||
* of memory and then break it up into "new_size"-sized blocks, adding
|
||||
* them to the free list.
|
||||
*/
|
||||
if (freelists[new_size] == NULL) {
|
||||
int i, frags;
|
||||
size_t total_size;
|
||||
void *new;
|
||||
char *curr, *next;
|
||||
|
||||
#ifdef MEMCLUSTER_BIG_MALLOC
|
||||
if (basic_blocks == NULL) {
|
||||
new = malloc(NUM_BASIC_BLOCKS * mem_target);
|
||||
if (new == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
curr = new;
|
||||
next = curr + mem_target;
|
||||
for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
|
||||
((memcluster_element *)curr)->next = next;
|
||||
curr = next;
|
||||
next += mem_target;
|
||||
}
|
||||
/*
|
||||
* curr is now pointing at the last block in the
|
||||
* array.
|
||||
*/
|
||||
((memcluster_element *)curr)->next = NULL;
|
||||
basic_blocks = new;
|
||||
}
|
||||
total_size = mem_target;
|
||||
new = basic_blocks;
|
||||
basic_blocks = basic_blocks->next;
|
||||
#else
|
||||
if (new_size > mem_target_half)
|
||||
total_size = mem_target_fudge;
|
||||
else
|
||||
total_size = mem_target;
|
||||
new = malloc(total_size);
|
||||
if (new == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
frags = total_size / new_size;
|
||||
stats[new_size].blocks++;
|
||||
stats[new_size].freefrags += frags;
|
||||
/* Set up a linked-list of blocks of size "new_size". */
|
||||
curr = new;
|
||||
next = curr + new_size;
|
||||
for (i = 0; i < (frags - 1); i++) {
|
||||
#if defined (DEBUGGING_MEMCLUSTER)
|
||||
memset(curr, 0xa5, new_size);
|
||||
#endif
|
||||
((memcluster_element *)curr)->next = next;
|
||||
curr = next;
|
||||
next += new_size;
|
||||
}
|
||||
/* curr is now pointing at the last block in the array. */
|
||||
#if defined (DEBUGGING_MEMCLUSTER)
|
||||
memset(curr, 0xa5, new_size);
|
||||
#endif
|
||||
((memcluster_element *)curr)->next = freelists[new_size];
|
||||
freelists[new_size] = new;
|
||||
}
|
||||
|
||||
/* The free list uses the "rounded-up" size "new_size". */
|
||||
#if defined (DEBUGGING_MEMCLUSTER)
|
||||
e = freelists[new_size];
|
||||
ret = (char *)e + sizeof *e;
|
||||
/*
|
||||
* Check to see if this buffer has been written to while on free list.
|
||||
*/
|
||||
check(ret, 0xa5, new_size - sizeof *e);
|
||||
/*
|
||||
* Mark memory we are returning.
|
||||
*/
|
||||
memset(ret, 0xe5, size);
|
||||
#else
|
||||
ret = freelists[new_size];
|
||||
#endif
|
||||
freelists[new_size] = freelists[new_size]->next;
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
e->next = NULL;
|
||||
e->size = size;
|
||||
e->fencepost = FRONT_FENCEPOST;
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
e->file = file;
|
||||
e->line = line;
|
||||
e->next = activelists[size];
|
||||
activelists[size] = e;
|
||||
#endif
|
||||
p = (char *)e + sizeof *e + size;
|
||||
memcpy(p, &fp, sizeof fp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The stats[] uses the _actual_ "size" requested by the
|
||||
* caller, with the caveat (in the code above) that "size" >= the
|
||||
* max. size (max_size) ends up getting recorded as a call to
|
||||
* max_size.
|
||||
*/
|
||||
stats[size].gets++;
|
||||
stats[size].totalgets++;
|
||||
stats[new_size].freefrags--;
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
return ((char *)e + sizeof *e);
|
||||
#else
|
||||
return (ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a call from an external caller,
|
||||
* so we want to count this as a user "put".
|
||||
*/
|
||||
void
|
||||
__memput(void *mem, size_t size) {
|
||||
__memput_record(mem, size, NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
__memput_record(void *mem, size_t size, const char *file, int line) {
|
||||
size_t new_size = quantize(size);
|
||||
#if defined (DEBUGGING_MEMCLUSTER)
|
||||
memcluster_element *e;
|
||||
memcluster_element *el;
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
memcluster_element *prev;
|
||||
#endif
|
||||
fence_t fp;
|
||||
char *p;
|
||||
#endif
|
||||
|
||||
#if !defined (MEMCLUSTER_RECORD)
|
||||
UNUSED(file);
|
||||
UNUSED(line);
|
||||
#endif
|
||||
|
||||
REQUIRE(freelists != NULL);
|
||||
|
||||
if (size == 0U) {
|
||||
errno = EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined (DEBUGGING_MEMCLUSTER)
|
||||
e = (memcluster_element *) ((char *)mem - sizeof *e);
|
||||
INSIST(e->fencepost == FRONT_FENCEPOST);
|
||||
INSIST(e->size == size);
|
||||
p = (char *)e + sizeof *e + size;
|
||||
memcpy(&fp, p, sizeof fp);
|
||||
INSIST(fp == BACK_FENCEPOST);
|
||||
INSIST(((int)mem % 4) == 0);
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
prev = NULL;
|
||||
if (size == max_size || new_size >= max_size)
|
||||
el = activelists[max_size];
|
||||
else
|
||||
el = activelists[size];
|
||||
while (el != NULL && el != e) {
|
||||
prev = el;
|
||||
el = el->next;
|
||||
}
|
||||
INSIST(el != NULL); /* double free */
|
||||
if (prev == NULL) {
|
||||
if (size == max_size || new_size >= max_size)
|
||||
activelists[max_size] = el->next;
|
||||
else
|
||||
activelists[size] = el->next;
|
||||
} else
|
||||
prev->next = el->next;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (size == max_size || new_size >= max_size) {
|
||||
/* memput() called on something beyond our upper limit */
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
free(e);
|
||||
#else
|
||||
free(mem);
|
||||
#endif
|
||||
|
||||
INSIST(stats[max_size].gets != 0U);
|
||||
stats[max_size].gets--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The free list uses the "rounded-up" size "new_size": */
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
memset(mem, 0xa5, new_size - sizeof *e); /* catch write after free */
|
||||
e->size = 0; /* catch double memput() */
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
e->file = file;
|
||||
e->line = line;
|
||||
#endif
|
||||
#ifdef MEMCLUSTER_ATEND
|
||||
e->next = NULL;
|
||||
el = freelists[new_size];
|
||||
while (el != NULL && el->next != NULL)
|
||||
el = el->next;
|
||||
if (el)
|
||||
el->next = e;
|
||||
else
|
||||
freelists[new_size] = e;
|
||||
#else
|
||||
e->next = freelists[new_size];
|
||||
freelists[new_size] = (void *)e;
|
||||
#endif
|
||||
#else
|
||||
((memcluster_element *)mem)->next = freelists[new_size];
|
||||
freelists[new_size] = (memcluster_element *)mem;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The stats[] uses the _actual_ "size" requested by the
|
||||
* caller, with the caveat (in the code above) that "size" >= the
|
||||
* max. size (max_size) ends up getting recorded as a call to
|
||||
* max_size.
|
||||
*/
|
||||
INSIST(stats[size].gets != 0U);
|
||||
stats[size].gets--;
|
||||
stats[new_size].freefrags++;
|
||||
}
|
||||
|
||||
void *
|
||||
__memget_debug(size_t size, const char *file, int line) {
|
||||
void *ptr;
|
||||
ptr = __memget_record(size, file, line);
|
||||
fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
|
||||
(u_long)size, ptr);
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
void
|
||||
__memput_debug(void *ptr, size_t size, const char *file, int line) {
|
||||
fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, ptr,
|
||||
(u_long)size);
|
||||
__memput_record(ptr, size, file, line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the stats[] on the stream "out" with suitable formatting.
|
||||
*/
|
||||
void
|
||||
memstats(FILE *out) {
|
||||
size_t i;
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
memcluster_element *e;
|
||||
#endif
|
||||
|
||||
if (freelists == NULL)
|
||||
return;
|
||||
for (i = 1; i <= max_size; i++) {
|
||||
const struct stats *s = &stats[i];
|
||||
|
||||
if (s->totalgets == 0U && s->gets == 0U)
|
||||
continue;
|
||||
fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
|
||||
(i == max_size) ? ">=" : " ",
|
||||
(unsigned long)i, s->totalgets, s->gets);
|
||||
if (s->blocks != 0U)
|
||||
fprintf(out, " (%lu bl, %lu ff)",
|
||||
s->blocks, s->freefrags);
|
||||
fputc('\n', out);
|
||||
}
|
||||
#ifdef MEMCLUSTER_RECORD
|
||||
fprintf(out, "Active Memory:\n");
|
||||
for (i = 1; i <= max_size; i++) {
|
||||
if ((e = activelists[i]) != NULL)
|
||||
while (e != NULL) {
|
||||
fprintf(out, "%s:%d %p:%d\n",
|
||||
e->file != NULL ? e->file :
|
||||
"<UNKNOWN>", e->line,
|
||||
(char *)e + sizeof *e, e->size);
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
memactive(void) {
|
||||
size_t i;
|
||||
|
||||
if (stats == NULL)
|
||||
return (0);
|
||||
for (i = 1; i <= max_size; i++)
|
||||
if (stats[i].gets != 0U)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Private. */
|
||||
|
||||
/*
|
||||
* Round up size to a multiple of sizeof(void *). This guarantees that a
|
||||
* block is at least sizeof void *, and that we won't violate alignment
|
||||
* restrictions, both of which are needed to make lists of blocks.
|
||||
*/
|
||||
static size_t
|
||||
quantize(size_t size) {
|
||||
int remainder;
|
||||
/*
|
||||
* If there is no remainder for the integer division of
|
||||
*
|
||||
* (rightsize/P_SIZE)
|
||||
*
|
||||
* then we already have a good size; if not, then we need
|
||||
* to round up the result in order to get a size big
|
||||
* enough to satisfy the request _and_ aligned on P_SIZE boundaries.
|
||||
*/
|
||||
remainder = size % P_SIZE;
|
||||
if (remainder != 0)
|
||||
size += P_SIZE - remainder;
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
return (size + SMALL_SIZE_LIMIT + sizeof (int));
|
||||
#else
|
||||
return (size);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DEBUGGING_MEMCLUSTER)
|
||||
static void
|
||||
check(unsigned char *a, int value, size_t len) {
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++)
|
||||
INSIST(a[i] == value);
|
||||
}
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (c) 2000 by Internet Software Consortium, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <port_before.h>
|
||||
#include <stdio.h>
|
||||
#include <isc/misc.h>
|
||||
#include <port_after.h>
|
||||
#ifndef HAVE_MOVEFILE
|
||||
/*
|
||||
* rename() is lame (can't overwrite an existing file) on some systems.
|
||||
* use movefile() instead, and let lame OS ports do what they need to.
|
||||
*/
|
||||
|
||||
int
|
||||
isc_movefile(const char *oldname, const char *newname) {
|
||||
return (rename(oldname, newname));
|
||||
}
|
||||
#else
|
||||
static int os_port_has_isc_movefile = 1;
|
||||
#endif
|
||||
@@ -1,532 +0,0 @@
|
||||
#ifndef LINT
|
||||
static const char rcsid[] = "$Id$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* tree - balanced binary tree library
|
||||
*
|
||||
* vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names]
|
||||
* vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes]
|
||||
* vix 23jun86 [added delete uar to add for replaced nodes]
|
||||
* vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224]
|
||||
* vix 06feb86 [added tree_mung()]
|
||||
* vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221]
|
||||
* vix 14dec85 [written]
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program text was created by Paul Vixie using examples from the book:
|
||||
* "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN
|
||||
* 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul
|
||||
* Vixie's.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
||||
* Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*#define DEBUG "tree"*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#include <isc/memcluster.h>
|
||||
#include <isc/tree.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
static int debugDepth = 0;
|
||||
static char *debugFuncs[256];
|
||||
# define ENTER(proc) { \
|
||||
debugFuncs[debugDepth] = proc; \
|
||||
fprintf(stderr, "ENTER(%d:%s.%s)\n", \
|
||||
debugDepth, DEBUG, \
|
||||
debugFuncs[debugDepth]); \
|
||||
debugDepth++; \
|
||||
}
|
||||
# define RET(value) { \
|
||||
debugDepth--; \
|
||||
fprintf(stderr, "RET(%d:%s.%s)\n", \
|
||||
debugDepth, DEBUG, \
|
||||
debugFuncs[debugDepth]); \
|
||||
return (value); \
|
||||
}
|
||||
# define RETV { \
|
||||
debugDepth--; \
|
||||
fprintf(stderr, "RETV(%d:%s.%s)\n", \
|
||||
debugDepth, DEBUG, \
|
||||
debugFuncs[debugDepth]); \
|
||||
return; \
|
||||
}
|
||||
# define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg);
|
||||
#else
|
||||
# define ENTER(proc) ;
|
||||
# define RET(value) return (value);
|
||||
# define RETV return;
|
||||
# define MSG(msg) ;
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
# define FALSE 0
|
||||
#endif
|
||||
|
||||
static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)());
|
||||
static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *);
|
||||
static void del(tree **, int *, tree **, void (*)(), int *);
|
||||
static void bal_L(tree **, int *);
|
||||
static void bal_R(tree **, int *);
|
||||
|
||||
void
|
||||
tree_init(tree **ppr_tree) {
|
||||
ENTER("tree_init")
|
||||
*ppr_tree = NULL;
|
||||
RETV
|
||||
}
|
||||
|
||||
tree_t
|
||||
tree_srch(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), tree_t p_user) {
|
||||
ENTER("tree_srch")
|
||||
|
||||
if (*ppr_tree) {
|
||||
int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data);
|
||||
|
||||
if (i_comp > 0)
|
||||
RET(tree_srch(&(**ppr_tree).right,
|
||||
pfi_compare,
|
||||
p_user))
|
||||
|
||||
if (i_comp < 0)
|
||||
RET(tree_srch(&(**ppr_tree).left,
|
||||
pfi_compare,
|
||||
p_user))
|
||||
|
||||
/* not higher, not lower... this must be the one.
|
||||
*/
|
||||
RET((**ppr_tree).data)
|
||||
}
|
||||
|
||||
/* grounded. NOT found.
|
||||
*/
|
||||
RET(NULL)
|
||||
}
|
||||
|
||||
tree_t
|
||||
tree_add(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t),
|
||||
tree_t p_user, void (*pfv_uar)())
|
||||
{
|
||||
int i_balance = FALSE;
|
||||
|
||||
ENTER("tree_add")
|
||||
if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar))
|
||||
RET(NULL)
|
||||
RET(p_user)
|
||||
}
|
||||
|
||||
int
|
||||
tree_delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t),
|
||||
tree_t p_user, void (*pfv_uar)())
|
||||
{
|
||||
int i_balance = FALSE, i_uar_called = FALSE;
|
||||
|
||||
ENTER("tree_delete");
|
||||
RET(delete(ppr_p, pfi_compare, p_user, pfv_uar,
|
||||
&i_balance, &i_uar_called))
|
||||
}
|
||||
|
||||
int
|
||||
tree_trav(tree **ppr_tree, int (*pfi_uar)(tree_t)) {
|
||||
ENTER("tree_trav")
|
||||
|
||||
if (!*ppr_tree)
|
||||
RET(TRUE)
|
||||
|
||||
if (!tree_trav(&(**ppr_tree).left, pfi_uar))
|
||||
RET(FALSE)
|
||||
if (!(*pfi_uar)((**ppr_tree).data))
|
||||
RET(FALSE)
|
||||
if (!tree_trav(&(**ppr_tree).right, pfi_uar))
|
||||
RET(FALSE)
|
||||
RET(TRUE)
|
||||
}
|
||||
|
||||
void
|
||||
tree_mung(tree **ppr_tree, void (*pfv_uar)(tree_t)) {
|
||||
ENTER("tree_mung")
|
||||
if (*ppr_tree) {
|
||||
tree_mung(&(**ppr_tree).left, pfv_uar);
|
||||
tree_mung(&(**ppr_tree).right, pfv_uar);
|
||||
if (pfv_uar)
|
||||
(*pfv_uar)((**ppr_tree).data);
|
||||
memput(*ppr_tree, sizeof(tree));
|
||||
*ppr_tree = NULL;
|
||||
}
|
||||
RETV
|
||||
}
|
||||
|
||||
static tree *
|
||||
sprout(tree **ppr, tree_t p_data, int *pi_balance,
|
||||
int (*pfi_compare)(tree_t, tree_t), void (*pfv_delete)(tree_t))
|
||||
{
|
||||
tree *p1, *p2, *sub;
|
||||
int cmp;
|
||||
|
||||
ENTER("sprout")
|
||||
|
||||
/* are we grounded? if so, add the node "here" and set the rebalance
|
||||
* flag, then exit.
|
||||
*/
|
||||
if (!*ppr) {
|
||||
MSG("grounded. adding new node, setting h=true")
|
||||
*ppr = (tree *) memget(sizeof(tree));
|
||||
if (*ppr) {
|
||||
(*ppr)->left = NULL;
|
||||
(*ppr)->right = NULL;
|
||||
(*ppr)->bal = 0;
|
||||
(*ppr)->data = p_data;
|
||||
*pi_balance = TRUE;
|
||||
}
|
||||
RET(*ppr);
|
||||
}
|
||||
|
||||
/* compare the data using routine passed by caller.
|
||||
*/
|
||||
cmp = (*pfi_compare)(p_data, (*ppr)->data);
|
||||
|
||||
/* if LESS, prepare to move to the left.
|
||||
*/
|
||||
if (cmp < 0) {
|
||||
MSG("LESS. sprouting left.")
|
||||
sub = sprout(&(*ppr)->left, p_data, pi_balance,
|
||||
pfi_compare, pfv_delete);
|
||||
if (sub && *pi_balance) { /* left branch has grown */
|
||||
MSG("LESS: left branch has grown")
|
||||
switch ((*ppr)->bal) {
|
||||
case 1:
|
||||
/* right branch WAS longer; bal is ok now */
|
||||
MSG("LESS: case 1.. bal restored implicitly")
|
||||
(*ppr)->bal = 0;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 0:
|
||||
/* balance WAS okay; now left branch longer */
|
||||
MSG("LESS: case 0.. balnce bad but still ok")
|
||||
(*ppr)->bal = -1;
|
||||
break;
|
||||
case -1:
|
||||
/* left branch was already too long. rebal */
|
||||
MSG("LESS: case -1: rebalancing")
|
||||
p1 = (*ppr)->left;
|
||||
if (p1->bal == -1) { /* LL */
|
||||
MSG("LESS: single LL")
|
||||
(*ppr)->left = p1->right;
|
||||
p1->right = *ppr;
|
||||
(*ppr)->bal = 0;
|
||||
*ppr = p1;
|
||||
} else { /* double LR */
|
||||
MSG("LESS: double LR")
|
||||
|
||||
p2 = p1->right;
|
||||
p1->right = p2->left;
|
||||
p2->left = p1;
|
||||
|
||||
(*ppr)->left = p2->right;
|
||||
p2->right = *ppr;
|
||||
|
||||
if (p2->bal == -1)
|
||||
(*ppr)->bal = 1;
|
||||
else
|
||||
(*ppr)->bal = 0;
|
||||
|
||||
if (p2->bal == 1)
|
||||
p1->bal = -1;
|
||||
else
|
||||
p1->bal = 0;
|
||||
*ppr = p2;
|
||||
} /*else*/
|
||||
(*ppr)->bal = 0;
|
||||
*pi_balance = FALSE;
|
||||
} /*switch*/
|
||||
} /*if*/
|
||||
RET(sub)
|
||||
} /*if*/
|
||||
|
||||
/* if MORE, prepare to move to the right.
|
||||
*/
|
||||
if (cmp > 0) {
|
||||
MSG("MORE: sprouting to the right")
|
||||
sub = sprout(&(*ppr)->right, p_data, pi_balance,
|
||||
pfi_compare, pfv_delete);
|
||||
if (sub && *pi_balance) {
|
||||
MSG("MORE: right branch has grown")
|
||||
|
||||
switch ((*ppr)->bal) {
|
||||
case -1:
|
||||
MSG("MORE: balance was off, fixed implicitly")
|
||||
(*ppr)->bal = 0;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 0:
|
||||
MSG("MORE: balance was okay, now off but ok")
|
||||
(*ppr)->bal = 1;
|
||||
break;
|
||||
case 1:
|
||||
MSG("MORE: balance was off, need to rebalance")
|
||||
p1 = (*ppr)->right;
|
||||
if (p1->bal == 1) { /* RR */
|
||||
MSG("MORE: single RR")
|
||||
(*ppr)->right = p1->left;
|
||||
p1->left = *ppr;
|
||||
(*ppr)->bal = 0;
|
||||
*ppr = p1;
|
||||
} else { /* double RL */
|
||||
MSG("MORE: double RL")
|
||||
|
||||
p2 = p1->left;
|
||||
p1->left = p2->right;
|
||||
p2->right = p1;
|
||||
|
||||
(*ppr)->right = p2->left;
|
||||
p2->left = *ppr;
|
||||
|
||||
if (p2->bal == 1)
|
||||
(*ppr)->bal = -1;
|
||||
else
|
||||
(*ppr)->bal = 0;
|
||||
|
||||
if (p2->bal == -1)
|
||||
p1->bal = 1;
|
||||
else
|
||||
p1->bal = 0;
|
||||
|
||||
*ppr = p2;
|
||||
} /*else*/
|
||||
(*ppr)->bal = 0;
|
||||
*pi_balance = FALSE;
|
||||
} /*switch*/
|
||||
} /*if*/
|
||||
RET(sub)
|
||||
} /*if*/
|
||||
|
||||
/* not less, not more: this is the same key! replace...
|
||||
*/
|
||||
MSG("FOUND: Replacing data value")
|
||||
*pi_balance = FALSE;
|
||||
if (pfv_delete)
|
||||
(*pfv_delete)((*ppr)->data);
|
||||
(*ppr)->data = p_data;
|
||||
RET(*ppr)
|
||||
}
|
||||
|
||||
static int
|
||||
delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), tree_t p_user,
|
||||
void (*pfv_uar)(tree_t), int *pi_balance, int *pi_uar_called)
|
||||
{
|
||||
tree *pr_q;
|
||||
int i_comp, i_ret;
|
||||
|
||||
ENTER("delete")
|
||||
|
||||
if (*ppr_p == NULL) {
|
||||
MSG("key not in tree")
|
||||
RET(FALSE)
|
||||
}
|
||||
|
||||
i_comp = (*pfi_compare)((*ppr_p)->data, p_user);
|
||||
if (i_comp > 0) {
|
||||
MSG("too high - scan left")
|
||||
i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar,
|
||||
pi_balance, pi_uar_called);
|
||||
if (*pi_balance)
|
||||
bal_L(ppr_p, pi_balance);
|
||||
} else if (i_comp < 0) {
|
||||
MSG("too low - scan right")
|
||||
i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar,
|
||||
pi_balance, pi_uar_called);
|
||||
if (*pi_balance)
|
||||
bal_R(ppr_p, pi_balance);
|
||||
} else {
|
||||
MSG("equal")
|
||||
pr_q = *ppr_p;
|
||||
if (pr_q->right == NULL) {
|
||||
MSG("right subtree null")
|
||||
*ppr_p = pr_q->left;
|
||||
*pi_balance = TRUE;
|
||||
} else if (pr_q->left == NULL) {
|
||||
MSG("right subtree non-null, left subtree null")
|
||||
*ppr_p = pr_q->right;
|
||||
*pi_balance = TRUE;
|
||||
} else {
|
||||
MSG("neither subtree null")
|
||||
del(&pr_q->left, pi_balance, &pr_q,
|
||||
pfv_uar, pi_uar_called);
|
||||
if (*pi_balance)
|
||||
bal_L(ppr_p, pi_balance);
|
||||
}
|
||||
if (!*pi_uar_called && pfv_uar)
|
||||
(*pfv_uar)(pr_q->data);
|
||||
/* Thanks to [email protected] for the following stmt. */
|
||||
memput(pr_q, sizeof(tree));
|
||||
i_ret = TRUE;
|
||||
}
|
||||
RET(i_ret)
|
||||
}
|
||||
|
||||
static void
|
||||
del(tree **ppr_r, int *pi_balance, tree **ppr_q,
|
||||
void (*pfv_uar)(tree_t), int *pi_uar_called)
|
||||
{
|
||||
ENTER("del")
|
||||
|
||||
if ((*ppr_r)->right != NULL) {
|
||||
del(&(*ppr_r)->right, pi_balance, ppr_q,
|
||||
pfv_uar, pi_uar_called);
|
||||
if (*pi_balance)
|
||||
bal_R(ppr_r, pi_balance);
|
||||
} else {
|
||||
if (pfv_uar)
|
||||
(*pfv_uar)((*ppr_q)->data);
|
||||
*pi_uar_called = TRUE;
|
||||
(*ppr_q)->data = (*ppr_r)->data;
|
||||
*ppr_q = *ppr_r;
|
||||
*ppr_r = (*ppr_r)->left;
|
||||
*pi_balance = TRUE;
|
||||
}
|
||||
|
||||
RETV
|
||||
}
|
||||
|
||||
static void
|
||||
bal_L(tree **ppr_p, int *pi_balance) {
|
||||
tree *p1, *p2;
|
||||
int b1, b2;
|
||||
|
||||
ENTER("bal_L")
|
||||
MSG("left branch has shrunk")
|
||||
|
||||
switch ((*ppr_p)->bal) {
|
||||
case -1:
|
||||
MSG("was imbalanced, fixed implicitly")
|
||||
(*ppr_p)->bal = 0;
|
||||
break;
|
||||
case 0:
|
||||
MSG("was okay, is now one off")
|
||||
(*ppr_p)->bal = 1;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 1:
|
||||
MSG("was already off, this is too much")
|
||||
p1 = (*ppr_p)->right;
|
||||
b1 = p1->bal;
|
||||
if (b1 >= 0) {
|
||||
MSG("single RR")
|
||||
(*ppr_p)->right = p1->left;
|
||||
p1->left = *ppr_p;
|
||||
if (b1 == 0) {
|
||||
MSG("b1 == 0")
|
||||
(*ppr_p)->bal = 1;
|
||||
p1->bal = -1;
|
||||
*pi_balance = FALSE;
|
||||
} else {
|
||||
MSG("b1 != 0")
|
||||
(*ppr_p)->bal = 0;
|
||||
p1->bal = 0;
|
||||
}
|
||||
*ppr_p = p1;
|
||||
} else {
|
||||
MSG("double RL")
|
||||
p2 = p1->left;
|
||||
b2 = p2->bal;
|
||||
p1->left = p2->right;
|
||||
p2->right = p1;
|
||||
(*ppr_p)->right = p2->left;
|
||||
p2->left = *ppr_p;
|
||||
if (b2 == 1)
|
||||
(*ppr_p)->bal = -1;
|
||||
else
|
||||
(*ppr_p)->bal = 0;
|
||||
if (b2 == -1)
|
||||
p1->bal = 1;
|
||||
else
|
||||
p1->bal = 0;
|
||||
*ppr_p = p2;
|
||||
p2->bal = 0;
|
||||
}
|
||||
}
|
||||
RETV
|
||||
}
|
||||
|
||||
static void
|
||||
bal_R(tree **ppr_p, int *pi_balance) {
|
||||
tree *p1, *p2;
|
||||
int b1, b2;
|
||||
|
||||
ENTER("bal_R")
|
||||
MSG("right branch has shrunk")
|
||||
switch ((*ppr_p)->bal) {
|
||||
case 1:
|
||||
MSG("was imbalanced, fixed implicitly")
|
||||
(*ppr_p)->bal = 0;
|
||||
break;
|
||||
case 0:
|
||||
MSG("was okay, is now one off")
|
||||
(*ppr_p)->bal = -1;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case -1:
|
||||
MSG("was already off, this is too much")
|
||||
p1 = (*ppr_p)->left;
|
||||
b1 = p1->bal;
|
||||
if (b1 <= 0) {
|
||||
MSG("single LL")
|
||||
(*ppr_p)->left = p1->right;
|
||||
p1->right = *ppr_p;
|
||||
if (b1 == 0) {
|
||||
MSG("b1 == 0")
|
||||
(*ppr_p)->bal = -1;
|
||||
p1->bal = 1;
|
||||
*pi_balance = FALSE;
|
||||
} else {
|
||||
MSG("b1 != 0")
|
||||
(*ppr_p)->bal = 0;
|
||||
p1->bal = 0;
|
||||
}
|
||||
*ppr_p = p1;
|
||||
} else {
|
||||
MSG("double LR")
|
||||
p2 = p1->right;
|
||||
b2 = p2->bal;
|
||||
p1->right = p2->left;
|
||||
p2->left = p1;
|
||||
(*ppr_p)->left = p2->right;
|
||||
p2->right = *ppr_p;
|
||||
if (b2 == -1)
|
||||
(*ppr_p)->bal = 1;
|
||||
else
|
||||
(*ppr_p)->bal = 0;
|
||||
if (b2 == 1)
|
||||
p1->bal = -1;
|
||||
else
|
||||
p1->bal = 0;
|
||||
*ppr_p = p2;
|
||||
p2->bal = 0;
|
||||
}
|
||||
}
|
||||
RETV
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user