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:
Waldemar Kornewald
2005-12-20 10:54:58 +00:00
parent 5d7cf21bdf
commit ce823541ec
127 changed files with 32 additions and 39826 deletions
-8
View File
@@ -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_ */
-8
View File
@@ -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
-8
View File
@@ -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_ */
-8
View File
@@ -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_ */
+1
View File
@@ -5,3 +5,4 @@ Package haiku-networkingkit-cvs :
;
SubInclude HAIKU_TOP src kits network compat ;
SubInclude HAIKU_TOP src kits network libnetwork ;
+5 -45
View File
@@ -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
-101
View File
@@ -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);
}
-153
View File
@@ -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);
}
-432
View File
@@ -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);
}
-113
View File
@@ -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*/
-592
View File
@@ -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
-140
View File
@@ -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
-154
View File
@@ -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
-107
View File
@@ -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);
}
-186
View File
@@ -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*/
-230
View File
@@ -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);
}
-116
View File
@@ -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
-532
View File
@@ -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