From: Jeff Garzik <jeff@garzik.org>
To: Pete Zaitcev <zaitcev@redhat.com>
Cc: Project Hail List <hail-devel@vger.kernel.org>
Subject: Re: [Patch 1/1] CLD: Introduce the "New CLD" API
Date: Tue, 09 Feb 2010 01:03:58 -0500 [thread overview]
Message-ID: <4B70FACE.7050304@garzik.org> (raw)
In-Reply-To: <20100208223517.2404ba3f@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1212 bytes --]
On 02/09/2010 12:35 AM, Pete Zaitcev wrote:
> On Mon, 08 Feb 2010 23:55:03 -0500
> Jeff Garzik<jeff@garzik.org> wrote:
>
>>>>> - if (cldc_getaddr(&host_list, hostb, NULL))
>>>>> + if (cldc_getaddr(&host_list, hostb,&ncld_log))
>>>>> return 1001;
>>>
>>>> Logging pointer should be supplied by the caller... that is the larger
>>>> bug. Needing a no-op log function is just an indication of that.
>>>
>>> I did it before, but then every client, without exception, needed
>>> to include<stdarg.h> and provide the log. And what for? This is
>>> STUPID and proof is in the pudding: your getsrvinfo does not do
>>> anything of the sort.
>>
>> Possibly true -- but it is worse to introduce internal inconsistencies.
>> It is far better to remove debugging statements completely than to
>> create inconsistent usage.
>
> Hmm, you may be right about that.
>
>>> Might as well replace cldc_getadd with getsrvinfo
>>> and then everyone becomes happy.
>>
>> Seems a good fit :)
>
> How far along were you with getsrvinfo? I only have the header
> that you sent to the list just before Christmas.
Coding complete, but needed testing. Probably works, since it came from
working code. See attached.
Jeff
[-- Attachment #2: getsrvinfo.h --]
[-- Type: text/plain, Size: 1233 bytes --]
#ifndef __GETSRVINFO_H__
#define __GETSRVINFO_H__
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
struct srvinfo;
enum srvinfo_error_codes {
ESI_NONE = 0, /* no error */
ESI_CORRUPT = 1, /* server returned bad data */
ESI_FAIL = 2, /* server returned permanent failure */
ESI_AGAIN = 3, /* server returned temporary failure;
* try again later.*/
ESI_OOM = 4, /* internal memory alloc failed */
ESI_INVAL = 5, /* invalid argument(s) */
};
enum srvinfo_flags {
FSI_NO_ADDR = (1U << 0), /* skip host->addrs lookup */
};
struct srvinfo {
unsigned int si_prio; /* SRV priority */
unsigned int si_weight; /* SRV weight */
char *si_target; /* SRV target domainname */
unsigned short si_port; /* SRV port */
struct addrinfo *si_addr; /* addresses returned
* from getaddrinfo(3) lookup
* on si_target */
struct srvinfo *si_next; /* next srvinfo in result list */
};
extern int getsrvinfo(const char *service_name, const char *domain_name,
const struct addrinfo *hints,
unsigned int flags, struct srvinfo **res);
extern void freesrvinfo(struct srvinfo *res);
extern const char *gsi_strerror(int errcode);
#endif /* __GETSRVINFO_H__ */
[-- Attachment #3: getsrvinfo.c --]
[-- Type: text/plain, Size: 5530 bytes --]
/*
* Copyright 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv.h>
#include "getsrvinfo.h"
#define __must_be_array(a) \
(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
enum {
gsi_max_dom_name_sz = 64,
gsi_dns_buf_sz = 1024,
};
static int fill_srvinfo(struct srvinfo *si,
const struct addrinfo *hints,
unsigned int gsi_flags,
unsigned int priority,
unsigned int weight, unsigned int port,
unsigned int nlen, const char *name)
{
char portstr[11];
char *hostname;
struct addrinfo *res0 = NULL;
int rc = 0;
sprintf(portstr, "%u", port);
hostname = malloc(nlen + 1);
if (!hostname)
return -ENOMEM;
memcpy(hostname, name, nlen);
hostname[nlen] = 0;
if (!(gsi_flags & FSI_NO_ADDR)) {
rc = getaddrinfo(hostname, portstr, hints, &res0);
/* because we do not wish failure of one lookup
* to cause failure of the entire operation,
* we simply record the lack of an address (NULL)
* and move on.
*/
if (rc)
res0 = NULL;
}
si->si_prio = priority;
si->si_weight = weight;
si->si_target = hostname;
si->si_port = port;
si->si_addr = res0;
si->si_next = NULL;
return 0;
}
void freesrvinfo(struct srvinfo *res)
{
while (res) {
struct srvinfo *tmp;
tmp = res;
res = res->si_next;
if (tmp->si_addr)
freeaddrinfo(tmp->si_addr);
free(tmp->si_target);
free(tmp);
}
}
int getsrvinfo(const char *service_name, const char *domain_name,
const struct addrinfo *hints, unsigned int gsi_flags,
struct srvinfo **res_out)
{
unsigned char resp[gsi_dns_buf_sz];
int rlen;
ns_msg nsb;
ns_rr rrb;
int rrlen;
char hostb[gsi_max_dom_name_sz];
struct srvinfo *si, *res = NULL, *res_last = NULL;
const unsigned char *p;
int rc, gsi_rc, i;
if (!domain_name || !res_out)
return ESI_INVAL;
*res_out = NULL;
/* we concatencate service_name and domain_name as a helpful
* service for the caller, because it is very common
* that service_name is either completely static, or at least
* stored in a separate variable from domain_name.
*/
if (service_name) {
char *name;
size_t name_len;
int has_dot;
has_dot = (service_name[strlen(service_name) - 1] == '.');
name_len = strlen(service_name) + strlen(domain_name) +
(has_dot ? 0 : 1) + 1;
name = malloc(name_len);
if (!name)
return ESI_OOM;
snprintf(name, name_len, "%s%s%s", service_name,
has_dot ? "" : ".",
domain_name);
rc = res_search(name, ns_c_in, ns_t_srv, resp, sizeof(resp));
free(name);
} else {
rc = res_search(domain_name, ns_c_in, ns_t_srv,
resp, sizeof(resp));
}
/* parse resolver return value */
if (rc < 0) {
switch (h_errno) {
case TRY_AGAIN:
return ESI_AGAIN;
case HOST_NOT_FOUND:
case NO_DATA:
case NO_RECOVERY:
default:
return ESI_FAIL;
}
}
rlen = rc;
if (rlen == 0)
return ESI_FAIL;
/* set up DNS result parse */
if (ns_initparse(resp, rlen, &nsb) < 0)
return ESI_CORRUPT;
/* iterate through each answer. Because DNS packets may
* be truncated, we do not signal an error on
* short-length faults found during packet parsing
*/
for (i = 0; i < ns_msg_count(nsb, ns_s_an); i++) {
rc = ns_parserr(&nsb, ns_s_an, i, &rrb);
if (rc < 0)
continue;
if (ns_rr_class(rrb) != ns_c_in)
continue;
switch (ns_rr_type(rrb)) {
case ns_t_srv:
rrlen = ns_rr_rdlen(rrb);
if (rrlen < 8) { /* 2+2+2 and 2 for host */
break;
}
p = ns_rr_rdata(rrb);
rc = dn_expand(resp, resp+rlen, p+6,
hostb, gsi_max_dom_name_sz);
if (rc < 0) {
break;
}
if (rc < 2) {
break;
}
si = malloc(sizeof(*si));
if (!si) {
gsi_rc = ESI_OOM;
goto err_out;
}
if (fill_srvinfo(si, hints, gsi_flags,
ns_get16(p+0),
ns_get16(p+2),
ns_get16(p+4),
rc, hostb)) {
free(si);
gsi_rc = ESI_OOM;
goto err_out;
}
/* if first item, set BOL-ptr */
if (!res)
res = si;
/* append to EOL */
if (res_last)
res_last->si_next = si;
res_last = si;
break;
case ns_t_cname: /* impossible, but ... ? */
default:
break;
}
}
*res_out = res;
return ESI_NONE;
err_out:
freesrvinfo(res);
return gsi_rc;
}
static const char *gsi_error_str[] = {
[ESI_NONE] = "no error",
[ESI_CORRUPT] = "server returned bad data",
[ESI_FAIL] = "server returned permanent failure",
[ESI_AGAIN] = "server returned temporary failure",
[ESI_OOM] = "internal memory alloc failed",
[ESI_INVAL] = "invalid argument(s)",
};
const char *gsi_strerror(int errcode)
{
if (errcode < 0 || errcode >= ARRAY_SIZE(gsi_error_str))
return NULL;
return gsi_error_str[errcode];
}
next prev parent reply other threads:[~2010-02-09 6:03 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-07 19:15 [Patch 1/1] CLD: Introduce the "New CLD" API Pete Zaitcev
2010-02-07 22:26 ` Jeff Garzik
2010-02-08 12:32 ` Jeff Garzik
2010-02-09 0:30 ` Pete Zaitcev
2010-02-09 6:25 ` Jeff Garzik
2010-02-09 1:46 ` Pete Zaitcev
2010-02-09 2:06 ` Jeff Garzik
2010-02-09 2:17 ` Pete Zaitcev
2010-02-09 4:55 ` Jeff Garzik
2010-02-09 5:35 ` Pete Zaitcev
2010-02-09 6:03 ` Jeff Garzik [this message]
2010-02-14 0:52 ` Jeff Garzik
2010-02-18 0:05 ` Pete Zaitcev
2010-02-18 1:18 ` Jeff Garzik
2010-02-19 1:35 ` Pete Zaitcev
2010-02-19 2:41 ` Jeff Garzik
2010-02-19 22:23 ` Pete Zaitcev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B70FACE.7050304@garzik.org \
--to=jeff@garzik.org \
--cc=hail-devel@vger.kernel.org \
--cc=zaitcev@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox