From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jeff Garzik Subject: Re: [Patch 1/1] CLD: Introduce the "New CLD" API Date: Tue, 09 Feb 2010 01:03:58 -0500 Message-ID: <4B70FACE.7050304@garzik.org> References: <20100207121550.7ee94ff6@redhat.com> <4B700478.3020305@garzik.org> <20100208184649.51374774@redhat.com> <4B70C319.6040005@garzik.org> <20100208191701.6e15b452@redhat.com> <4B70EAA7.4060806@garzik.org> <20100208223517.2404ba3f@redhat.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050008060502090205020000" Return-path: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:sender:message-id:date:from :user-agent:mime-version:to:cc:subject:references:in-reply-to :content-type; bh=TT8jc3uK+lZFRlcZ1P/A0YgVU1S2oOIFnV6ew83gkFo=; b=SMvHfNLpKxy8B+F30kejPiQbEMu8/vrp6bVP1YJdW2gnwAqn4kDoXheIuEtYJF59z4 pC4OoC7UnaTrH+0+rqv3DXERsMp24lBVtLFOvjurAc5SFZzK6apWwjAZDa6Nd8RO5iQA k2l01lepHuj07ZurRBZ+6XynirDr349goar7M= In-Reply-To: <20100208223517.2404ba3f@redhat.com> Sender: hail-devel-owner@vger.kernel.org List-ID: To: Pete Zaitcev Cc: Project Hail List This is a multi-part message in MIME format. --------------050008060502090205020000 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit On 02/09/2010 12:35 AM, Pete Zaitcev wrote: > On Mon, 08 Feb 2010 23:55:03 -0500 > Jeff Garzik 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 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 --------------050008060502090205020000 Content-Type: text/plain; name="getsrvinfo.h" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="getsrvinfo.h" #ifndef __GETSRVINFO_H__ #define __GETSRVINFO_H__ #include #include #include 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__ */ --------------050008060502090205020000 Content-Type: text/plain; name="getsrvinfo.c" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="getsrvinfo.c" /* * 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 #include #include #include #include #include #include #include #include #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]; } --------------050008060502090205020000--