sync wth 20010228-pl04.

This commit is contained in:
itojun 2001-08-09 08:10:17 +00:00
parent 9bbc26f3dc
commit 3c86caea97
7 changed files with 297 additions and 110 deletions

View File

@ -111,6 +111,14 @@ static void own_inet_addr_init(INET_ADDR_LIST *addr_list,
VAR_INET_INTERFACES, host);
myfree(hosts);
/*
* Weed out duplicate IP addresses. Duplicates happen when the same
* IP address is listed under multiple hostnames. If we don't weed
* out duplicates, Postfix can suddenly stop working after the DNS is
* changed.
*/
inet_addr_list_uniq(addr_list);
inet_addr_list_init(&local_addrs);
inet_addr_list_init(&local_masks);
if (inet_addr_local(&local_addrs, &local_masks) == 0)

View File

@ -534,7 +534,7 @@ SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
char *save;
char *dest;
char *cp;
int found_myself;
int found_myself = 0;
/*
* First try to deliver to the indicated destination, then try to deliver

View File

@ -269,6 +269,7 @@
#include <mymalloc.h>
#include <dict.h>
#include <htable.h>
#include <ctable.h>
/* DNS library. */
@ -310,9 +311,8 @@ static jmp_buf smtpd_check_buf;
* Intermediate results. These are static to avoid unnecessary stress on the
* memory manager routines.
*/
static RESOLVE_REPLY reply;
static VSTRING *query;
static VSTRING *error_text;
static CTABLE *smtpd_resolve_cache;
/*
* Pre-opened SMTP recipient maps so we can reject mail for unknown users.
@ -345,7 +345,7 @@ static HTABLE *smtpd_rest_classes;
/*
* The routine that recursively applies restrictions.
*/
static int generic_checks(SMTPD_STATE *, ARGV *, char *, char *, char *);
static int generic_checks(SMTPD_STATE *, ARGV *, const char *, const char *, const char *);
/*
* Reject context.
@ -360,6 +360,49 @@ static int generic_checks(SMTPD_STATE *, ARGV *, char *, char *, char *);
* YASLM.
*/
#define STR vstring_str
#define CONST_STR(x) ((const char *) vstring_str(x))
/* resolve_pagein - page in an address resolver result */
static void *resolve_pagein(const char *addr, void *unused_context)
{
static VSTRING *query;
RESOLVE_REPLY *reply;
/*
* Initialize on the fly.
*/
if (query == 0)
query = vstring_alloc(10);
/*
* Initialize.
*/
reply = (RESOLVE_REPLY *) mymalloc(sizeof(*reply));
resolve_clnt_init(reply);
/*
* Resolve the address.
*/
canon_addr_internal(query, addr);
resolve_clnt_query(STR(query), reply);
lowercase(STR(reply->recipient));
/*
* Save the result.
*/
return ((void *) reply);
}
/* resolve_pageout - page out an address resolver result */
static void resolve_pageout(void *data, void *unused_context)
{
RESOLVE_REPLY *reply = (RESOLVE_REPLY *) data;
resolve_clnt_free(reply);
myfree((void *) reply);
}
/* smtpd_check_parse - pre-parse restrictions */
@ -471,13 +514,16 @@ void smtpd_check_init(void)
DICT_FLAG_LOCK);
/*
* Reply is used as a cache for resolved addresses, and error_text is
* used for returning error responses.
* error_text is used for returning error responses.
*/
resolve_clnt_init(&reply);
query = vstring_alloc(10);
error_text = vstring_alloc(10);
/*
* Initialize the resolved address cache.
*/
smtpd_resolve_cache = ctable_create(100, resolve_pagein,
resolve_pageout, (void *) 0);
/*
* Pre-parse the restriction lists. At the same time, pre-open tables
* before going to jail.
@ -620,8 +666,10 @@ static const char *check_maps_find(SMTPD_STATE *state, const char *reply_name,
/* check_mail_addr_find - reject with temporary failure if dict lookup fails */
static const char *check_mail_addr_find(SMTPD_STATE *state, const char *reply_name,
MAPS *maps, const char *key, char **ext)
static const char *check_mail_addr_find(SMTPD_STATE *state,
const char *reply_name,
MAPS *maps, const char *key,
char **ext)
{
const char *result;
@ -820,8 +868,8 @@ static int reject_unknown_hostname(SMTPD_STATE *state, char *name,
/* reject_unknown_mailhost - fail if name has no A or MX record */
static int reject_unknown_mailhost(SMTPD_STATE *state, char *name,
char *reply_name, char *reply_class)
static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
const char *reply_name, const char *reply_class)
{
char *myname = "reject_unknown_mailhost";
int dns_status;
@ -881,7 +929,8 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
{
char *myname = "permit_auth_destination";
char *domain;
const RESOLVE_REPLY *reply;
const char *domain;
if (msg_verbose)
msg_info("%s: %s", myname, recipient);
@ -889,14 +938,13 @@ static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
/*
* Resolve the address.
*/
canon_addr_internal(query, recipient);
resolve_clnt_query(STR(query), &reply);
lowercase(STR(reply.recipient));
reply = (const RESOLVE_REPLY *)
ctable_locate(smtpd_resolve_cache, recipient);
/*
* Handle special case that is not supposed to happen.
*/
if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
@ -912,7 +960,7 @@ static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
/*
* Skip source-routed mail (uncertain destination).
*/
if (var_allow_untrust_route == 0 && (reply.flags & RESOLVE_FLAG_ROUTED))
if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED))
return (SMTPD_CHECK_DUNNO);
/*
@ -971,7 +1019,7 @@ static int reject_unauth_pipelining(SMTPD_STATE *state)
/* has_my_addr - see if this host name lists one of my network addresses */
static int has_my_addr(char *host)
static int has_my_addr(const char *host)
{
#ifdef INET6
char *myname = "has_my_addr";
@ -1059,7 +1107,8 @@ static int has_my_addr(char *host)
static int permit_mx_backup(SMTPD_STATE *state, const char *recipient)
{
char *myname = "permit_mx_backup";
char *domain;
const RESOLVE_REPLY *reply;
const char *domain;
DNS_RR *mx_list;
DNS_RR *mx;
@ -1071,15 +1120,14 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient)
/*
* Resolve the address.
*/
canon_addr_internal(query, recipient);
resolve_clnt_query(STR(query), &reply);
lowercase(STR(reply.recipient));
reply = (const RESOLVE_REPLY *)
ctable_locate(smtpd_resolve_cache, recipient);
/*
* If the destination is local, it is acceptable, because we are
* supposedly MX for our own address.
*/
if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
if (resolve_local(domain)
@ -1093,7 +1141,7 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient)
/*
* Skip source-routed mail (uncertain destination).
*/
if (var_allow_untrust_route == 0 && (reply.flags & RESOLVE_FLAG_ROUTED))
if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED))
return (SMTPD_CHECK_DUNNO);
/*
@ -1202,11 +1250,12 @@ static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr,
/* reject_unknown_address - fail if address does not resolve */
static int reject_unknown_address(SMTPD_STATE *state, char *addr,
char *reply_name, char *reply_class)
static int reject_unknown_address(SMTPD_STATE *state, const char *addr,
const char *reply_name, const char *reply_class)
{
char *myname = "reject_unknown_address";
char *domain;
const RESOLVE_REPLY *reply;
const char *domain;
if (msg_verbose)
msg_info("%s: %s", myname, addr);
@ -1214,14 +1263,12 @@ static int reject_unknown_address(SMTPD_STATE *state, char *addr,
/*
* Resolve the address.
*/
canon_addr_internal(query, addr);
resolve_clnt_query(STR(query), &reply);
lowercase(STR(reply.recipient));
reply = (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, addr);
/*
* Skip local destinations and non-DNS forms.
*/
if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
return (SMTPD_CHECK_DUNNO);
domain += 1;
if (resolve_local(domain)
@ -1241,10 +1288,11 @@ static int reject_unknown_address(SMTPD_STATE *state, char *addr,
/* check_table_result - translate table lookup result into pass/reject */
static int check_table_result(SMTPD_STATE *state, char *table,
static int check_table_result(SMTPD_STATE *state, const char *table,
const char *value, const char *datum,
char *reply_name, char *reply_class,
char *def_acl)
const char *reply_name,
const char *reply_class,
const char *def_acl)
{
char *myname = "check_table_result";
int code;
@ -1339,17 +1387,20 @@ static int check_table_result(SMTPD_STATE *state, char *table,
/* check_access - table lookup without substring magic */
static int check_access(SMTPD_STATE *state, char *table, char *name, int flags,
char *reply_name, char *reply_class, char *def_acl)
static int check_access(SMTPD_STATE *state, const char *table, const char *name,
int flags, int *found, const char *reply_name,
const char *reply_class, const char *def_acl)
{
char *myname = "check_access";
char *low_name = lowercase(mystrdup(name));
const char *value;
DICT *dict;
#define CHK_ACCESS_RETURN(x) { myfree(low_name); return(x); }
#define CHK_ACCESS_RETURN(x,y) { *found = y; myfree(low_name); return(x); }
#define FULL 0
#define PARTIAL DICT_FLAG_FIXED
#define FOUND 1
#define MISSED 0
if (msg_verbose)
msg_info("%s: %s", myname, name);
@ -1360,19 +1411,20 @@ static int check_access(SMTPD_STATE *state, char *table, char *name, int flags,
if ((value = dict_get(dict, low_name)) != 0)
CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
reply_name, reply_class,
def_acl));
def_acl), FOUND);
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO);
CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO, MISSED);
}
/* check_domain_access - domainname-based table lookup */
static int check_domain_access(SMTPD_STATE *state, char *table,
char *domain, int flags,
char *reply_name, char *reply_class,
char *def_acl)
static int check_domain_access(SMTPD_STATE *state, const char *table,
const char *domain, int flags,
int *found, const char *reply_name,
const char *reply_class,
const char *def_acl)
{
char *myname = "check_domain_access";
char *low_domain = lowercase(mystrdup(domain));
@ -1387,7 +1439,7 @@ static int check_domain_access(SMTPD_STATE *state, char *table,
/*
* Try the name and its parent domains. Including top-level domains.
*/
#define CHK_DOMAIN_RETURN(x) { myfree(low_domain); return(x); }
#define CHK_DOMAIN_RETURN(x,y) { *found = y; myfree(low_domain); return(x); }
if ((dict = dict_handle(table)) == 0)
msg_panic("%s: dictionary not found: %s", myname, table);
@ -1396,7 +1448,7 @@ static int check_domain_access(SMTPD_STATE *state, char *table,
if ((value = dict_get(dict, name)) != 0)
CHK_DOMAIN_RETURN(check_table_result(state, table, value,
domain, reply_name, reply_class,
def_acl));
def_acl), FOUND);
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
@ -1404,15 +1456,16 @@ static int check_domain_access(SMTPD_STATE *state, char *table,
break;
flags = PARTIAL;
}
CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO);
CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO, MISSED);
}
/* check_addr_access - address-based table lookup */
static int check_addr_access(SMTPD_STATE *state, char *table,
char *address, int flags,
char *reply_name, char *reply_class,
char *def_acl)
static int check_addr_access(SMTPD_STATE *state, const char *table,
const char *address, int flags,
int *found, const char *reply_name,
const char *reply_class,
const char *def_acl)
{
char *myname = "check_addr_access";
char *addr;
@ -1425,6 +1478,8 @@ static int check_addr_access(SMTPD_STATE *state, char *table,
/*
* Try the address and its parent networks.
*/
#define CHK_ADDR_RETURN(x,y) { *found = y; return(x); }
addr = STR(vstring_strcpy(error_text, address));
if ((dict = dict_handle(table)) == 0)
@ -1432,24 +1487,26 @@ static int check_addr_access(SMTPD_STATE *state, char *table,
do {
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, addr)) != 0)
return (check_table_result(state, table, value, address,
reply_name, reply_class,
def_acl));
CHK_ADDR_RETURN(check_table_result(state, table, value, address,
reply_name, reply_class,
def_acl), FOUND);
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
flags = PARTIAL;
} while (split_at_right(addr, '.'));
return (SMTPD_CHECK_DUNNO);
CHK_ADDR_RETURN(SMTPD_CHECK_DUNNO, MISSED);
}
/* check_namadr_access - OK/FAIL based on host name/address lookup */
static int check_namadr_access(SMTPD_STATE *state, char *table,
char *name, char *addr, int flags,
char *reply_name, char *reply_class,
char *def_acl)
static int check_namadr_access(SMTPD_STATE *state, const char *table,
const char *name, const char *addr,
int flags, int *found,
const char *reply_name,
const char *reply_class,
const char *def_acl)
{
char *myname = "check_namadr_access";
int status;
@ -1462,16 +1519,16 @@ static int check_namadr_access(SMTPD_STATE *state, char *table,
* wildcard may pre-empt a more specific address table entry.
*/
if ((status = check_domain_access(state, table, name, flags,
reply_name, reply_class,
def_acl)) != 0)
found, reply_name, reply_class,
def_acl)) != 0 || *found)
return (status);
/*
* Look up the network address, or parent networks thereof.
*/
if ((status = check_addr_access(state, table, addr, flags,
reply_name, reply_class,
def_acl)) != 0)
found, reply_name, reply_class,
def_acl)) != 0 || *found)
return (status);
/*
@ -1482,12 +1539,15 @@ static int check_namadr_access(SMTPD_STATE *state, char *table,
/* check_mail_access - OK/FAIL based on mail address lookup */
static int check_mail_access(SMTPD_STATE *state, char *table, char *addr,
char *reply_name, char *reply_class,
char *def_acl)
static int check_mail_access(SMTPD_STATE *state, const char *table,
const char *addr, int *found,
const char *reply_name,
const char *reply_class,
const char *def_acl)
{
char *myname = "check_mail_access";
char *ratsign;
const RESOLVE_REPLY *reply;
const char *ratsign;
int status;
char *local_at;
@ -1497,42 +1557,42 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr,
/*
* Resolve the address.
*/
canon_addr_internal(query, addr);
resolve_clnt_query(STR(query), &reply);
lowercase(STR(reply.recipient));
reply = (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, addr);
/*
* Garbage in, garbage out. Every address from canon_addr_internal() and
* from resolve_clnt_query() must be fully qualified.
*/
if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0) {
msg_warn("%s: no @domain in address: %s", myname, STR(reply.recipient));
if ((ratsign = strrchr(CONST_STR(reply->recipient), '@')) == 0) {
msg_warn("%s: no @domain in address: %s", myname, CONST_STR(reply->recipient));
return (0);
}
/*
* Look up the full address.
*/
if ((status = check_access(state, table, STR(reply.recipient), FULL,
reply_name, reply_class, def_acl)) != 0)
if ((status = check_access(state, table, CONST_STR(reply->recipient), FULL,
found, reply_name, reply_class, def_acl)) != 0
|| *found)
return (status);
/*
* Look up the domain name, or parent domains thereof.
*/
if ((status = check_domain_access(state, table, ratsign + 1, PARTIAL,
reply_name, reply_class, def_acl)) != 0)
found, reply_name, reply_class, def_acl)) != 0
|| *found)
return (status);
/*
* Look up localpart@
*/
local_at = mystrndup(STR(reply.recipient),
ratsign - STR(reply.recipient) + 1);
status = check_access(state, table, local_at, PARTIAL,
local_at = mystrndup(CONST_STR(reply->recipient),
ratsign - CONST_STR(reply->recipient) + 1);
status = check_access(state, table, local_at, PARTIAL, found,
reply_name, reply_class, def_acl);
myfree(local_at);
if (status != 0)
if (status != 0 || *found)
return (status);
/*
@ -1626,7 +1686,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
/* is_map_command - restriction has form: check_xxx_access type:name */
static int is_map_command(char *name, char *command, char ***argp)
static int is_map_command(const char *name, const char *command, char ***argp)
{
/*
@ -1649,13 +1709,16 @@ static int is_map_command(char *name, char *command, char ***argp)
/* generic_checks - generic restrictions */
static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
char *reply_name, char *reply_class, char *def_acl)
const char *reply_name,
const char *reply_class,
const char *def_acl)
{
char *myname = "generic_checks";
char **cpp;
char *name;
const char *name;
int status = 0;
ARGV *list;
int found;
if (msg_verbose)
msg_info("%s: START", myname);
@ -1702,7 +1765,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
status = permit_mynetworks(state);
} else if (is_map_command(name, CHECK_CLIENT_ACL, &cpp)) {
status = check_namadr_access(state, *cpp, state->name, state->addr,
FULL, state->namaddr,
FULL, &found, state->namaddr,
SMTPD_NAME_CLIENT, def_acl);
} else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
status = reject_maps_rbl(state);
@ -1714,7 +1777,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
else if (is_map_command(name, CHECK_HELO_ACL, &cpp)) {
if (state->helo_name)
status = check_domain_access(state, *cpp, state->helo_name,
FULL, state->helo_name,
FULL, &found, state->helo_name,
SMTPD_NAME_HELO, def_acl);
} else if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
if (state->helo_name) {
@ -1758,7 +1821,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
else if (is_map_command(name, CHECK_SENDER_ACL, &cpp)) {
if (state->sender && *state->sender)
status = check_mail_access(state, *cpp, state->sender,
state->sender,
&found, state->sender,
SMTPD_NAME_SENDER, def_acl);
} else if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) {
if (state->sender && *state->sender)
@ -1780,7 +1843,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
else if (is_map_command(name, CHECK_RECIP_ACL, &cpp)) {
if (state->recipient)
status = check_mail_access(state, *cpp, state->recipient,
state->recipient,
&found, state->recipient,
SMTPD_NAME_RECIPIENT, def_acl);
} else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) {
if (state->recipient)
@ -1820,7 +1883,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
else if (is_map_command(name, CHECK_ETRN_ACL, &cpp)) {
if (state->etrn_name)
status = check_domain_access(state, *cpp, state->etrn_name,
FULL, state->etrn_name,
FULL, &found, state->etrn_name,
SMTPD_NAME_ETRN, def_acl);
}
@ -2055,7 +2118,8 @@ char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
{
char *myname = "smtpd_check_rcptmap";
char *saved_recipient;
char *domain;
const RESOLVE_REPLY *reply;
const char *domain;
int status;
/*
@ -2082,14 +2146,13 @@ char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
/*
* Resolve the address.
*/
canon_addr_internal(query, recipient);
resolve_clnt_query(STR(query), &reply);
lowercase(STR(reply.recipient));
reply = (const RESOLVE_REPLY *)
ctable_locate(smtpd_resolve_cache, recipient);
/*
* Skip non-DNS forms. Skip non-local numerical forms.
*/
if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
SMTPD_CHECK_RCPT_RETURN(0);
domain += 1;
if (domain[0] == '#' || domain[0] == '[')
@ -2104,10 +2167,10 @@ char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
*/
if (*var_virtual_maps
&& (check_maps_find(state, recipient, virtual_maps, domain, 0))) {
if (NOMATCH(rcpt_canon_maps, STR(reply.recipient))
&& NOMATCH(canonical_maps, STR(reply.recipient))
&& NOMATCH(relocated_maps, STR(reply.recipient))
&& NOMATCH(virtual_maps, STR(reply.recipient))) {
if (NOMATCH(rcpt_canon_maps, CONST_STR(reply->recipient))
&& NOMATCH(canonical_maps, CONST_STR(reply->recipient))
&& NOMATCH(relocated_maps, CONST_STR(reply->recipient))
&& NOMATCH(virtual_maps, CONST_STR(reply->recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown", 550, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text));
@ -2120,11 +2183,11 @@ char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
* Sendmail-style virtual domains.
*/
if (*var_local_rcpt_maps && resolve_local(domain)) {
if (NOMATCH(rcpt_canon_maps, STR(reply.recipient))
&& NOMATCH(canonical_maps, STR(reply.recipient))
&& NOMATCH(relocated_maps, STR(reply.recipient))
&& NOMATCH(virtual_maps, STR(reply.recipient))
&& NOMATCH(local_rcpt_maps, STR(reply.recipient))) {
if (NOMATCH(rcpt_canon_maps, CONST_STR(reply->recipient))
&& NOMATCH(canonical_maps, CONST_STR(reply->recipient))
&& NOMATCH(relocated_maps, CONST_STR(reply->recipient))
&& NOMATCH(virtual_maps, CONST_STR(reply->recipient))
&& NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown", 550, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text));
@ -2389,11 +2452,19 @@ static void rest_class(char *class)
void resolve_clnt_init(RESOLVE_REPLY *reply)
{
reply->flags = 0;
reply->transport = vstring_alloc(100);
reply->nexthop = vstring_alloc(100);
reply->recipient = vstring_alloc(100);
}
void resolve_clnt_free(RESOLVE_REPLY *reply)
{
vstring_free(reply->transport);
vstring_free(reply->nexthop);
vstring_free(reply->recipient);
}
#ifdef USE_SASL_AUTH
bool var_smtpd_sasl_enable = 0;
@ -2436,7 +2507,7 @@ VSTRING *canon_addr_internal(VSTRING *result, const char *addr)
void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
{
if (addr == STR(reply->recipient))
if (addr == CONST_STR(reply->recipient))
msg_panic("resolve_clnt_query: result clobbers input");
vstring_strcpy(reply->transport, "foo");
vstring_strcpy(reply->nexthop, "foo");
@ -2458,7 +2529,7 @@ static NORETURN usage(char *myname)
msg_fatal("usage: %s", myname);
}
main(int argc, char **argv)
int main(int argc, char **argv)
{
VSTRING *buf = vstring_alloc(100);
SMTPD_STATE state;

View File

@ -24,7 +24,7 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \
sane_socketpair.c
sane_socketpair.c ctable.c
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
@ -50,7 +50,7 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \
sane_socketpair.o
sane_socketpair.o ctable.o
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
@ -67,7 +67,7 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h \
watchdog.h spawn_command.h sane_fsops.h dict_tcp.h hex_quote.h \
sane_time.h sane_socketpair.h
sane_time.h sane_socketpair.h ctable.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
@ -83,7 +83,8 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \
mystrtok sigdelay translit valid_hostname vstream_popen \
vstring vstring_vstream doze select_bug stream_test mac_expand \
watchdog unescape hex_quote name_mask rand_sleep sane_time
watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
inet_addr_list
LIB_DIR = ../../lib
INC_DIR = ../../include
@ -277,6 +278,16 @@ sane_time: $(LIB)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
ctable: $(LIB)
mv $@.o junk
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
inet_addr_list: $(LIB)
mv $@.o junk
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
@ -289,7 +300,7 @@ stream_test: stream_test.c $(LIB)
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
hex_quote_test
hex_quote_test ctable_test inet_addr_list_test
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
@ -312,6 +323,16 @@ hex_quote_test: hex_quote
cmp hex_quote.ref hex_quote.tmp
rm -f hex_quote.ref hex_quote.tmp
ctable_test: ctable
./ctable <ctable.in >ctable.tmp 2>&1
diff ctable.ref ctable.tmp
rm -f ctable.tmp
inet_addr_list_test: inet_addr_list
./inet_addr_list `cat inet_addr_list.in` >inet_addr_list.tmp 2>&1
diff inet_addr_list.ref inet_addr_list.tmp
rm -f inet_addr_list.tmp
DB_TYPE = `../postconf/postconf -h default_database_type`
dict_test: dict_open testdb dict_test.in dict_test.ref
@ -371,6 +392,13 @@ concatenate.o: mymalloc.h
concatenate.o: stringops.h
concatenate.o: vstring.h
concatenate.o: vbuf.h
ctable.o: ctable.c
ctable.o: sys_defs.h
ctable.o: msg.h
ctable.o: mymalloc.h
ctable.o: ring.h
ctable.o: htable.h
ctable.o: ctable.h
dict.o: dict.c
dict.o: sys_defs.h
dict.o: msg.h

View File

@ -13,6 +13,9 @@
/* INET_ADDR_LIST *list;
/* struct in_addr *addr;
/*
/* void inet_addr_list_uniq(list)
/* INET_ADDR_LIST *list;
/*
/* void inet_addr_list_free(list)
/* INET_ADDR_LIST *list;
/* DESCRIPTION
@ -25,6 +28,9 @@
/* inet_addr_list_append() appends the specified address to
/* the specified list, extending the list on the fly.
/*
/* inet_addr_list_uniq() sorts the specified address list and
/* eliminates duplicates.
/*
/* inet_addr_list_free() reclaims memory used for the
/* specified address list.
/* LICENSE
@ -43,6 +49,7 @@
#include <sys_defs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netdb.h>
@ -118,9 +125,81 @@ void inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
}
#endif
/* inet_addr_list_comp - compare addresses */
static int inet_addr_list_comp(const void *a, const void *b)
{
const struct in_addr *a_addr = (const struct in_addr *) a;
const struct in_addr *b_addr = (const struct in_addr *) b;
return (a_addr->s_addr - b_addr->s_addr);
}
/* inet_addr_list_uniq - weed out duplicates */
void inet_addr_list_uniq(INET_ADDR_LIST *list)
{
int n;
int m;
/*
* Put the identical members right next to each other.
*/
qsort((void *) list->addrs, list->used,
sizeof(list->addrs[0]), inet_addr_list_comp);
/*
* Nuke the duplicates. Postcondition after while loop: m is the largest
* index for which list->addrs[n] == list->addrs[m].
*/
for (m = n = 0; m < list->used; m++, n++) {
if (m != n)
list->addrs[n] = list->addrs[m];
while (m + 1 < list->used
&& inet_addr_list_comp((void *) &(list->addrs[n]),
(void *) &(list->addrs[m + 1])) == 0)
m += 1;
}
list->used = n;
}
/* inet_addr_list_free - destroy internet address list */
void inet_addr_list_free(INET_ADDR_LIST *list)
{
myfree((char *) list->addrs);
}
#ifdef TEST
/*
* Duplicate elimination needs to be tested.
*/
#include <inet_addr_host.h>
static void inet_addr_list_print(INET_ADDR_LIST *list)
{
int n;
for (n = 0; n < list->used; n++)
msg_info("%s", inet_ntoa(list->addrs[n]));
}
int main(int argc, char **argv)
{
INET_ADDR_LIST list;
inet_addr_list_init(&list);
while (--argc && *++argv)
if (inet_addr_host(&list, *argv) == 0)
msg_fatal("host not found: %s", *argv);
msg_info("list before sort/uniq");
inet_addr_list_print(&list);
inet_addr_list_uniq(&list);
msg_info("list after sort/uniq");
inet_addr_list_print(&list);
inet_addr_list_free(&list);
return (0);
}
#endif

View File

@ -31,6 +31,7 @@ typedef struct INET_ADDR_LIST {
extern void inet_addr_list_init(INET_ADDR_LIST *);
extern void inet_addr_list_free(INET_ADDR_LIST *);
extern void inet_addr_list_uniq(INET_ADDR_LIST *);
#ifdef INET6
struct sockaddr;
extern void inet_addr_list_append(INET_ADDR_LIST *, struct sockaddr *);

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.3 2001/03/13 18:34:23 itojun Exp $
# $NetBSD: Makefile,v 1.4 2001/08/09 08:10:19 itojun Exp $
LIB= util
@ -29,7 +29,7 @@ SRCS= argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \
sane_socketpair.c \
sane_socketpair.c ctable.c
# IPv6
SRCS+= get_port.c