This commit was generated by cvs2svn to compensate for changes in r119669,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
cc55dd3ffa
@ -1,6 +1,6 @@
|
||||
Internet Software Consortium DHCP Distribution
|
||||
Version 3.0.1
|
||||
Release Candidate 9
|
||||
Release Candidate 12
|
||||
April 28, 2002
|
||||
|
||||
README FILE
|
||||
@ -97,7 +97,7 @@ system.
|
||||
|
||||
RELEASE STATUS
|
||||
|
||||
This is the tenth release candidate of version 3.0.1 of the ISC DHCP
|
||||
This is the twelfth release candidate of version 3.0.1 of the ISC DHCP
|
||||
Distribution. Development of this release is approaching the point at
|
||||
which it will be frozen, and no significant new features will be
|
||||
added.
|
||||
|
@ -1,6 +1,6 @@
|
||||
Internet Software Consortium DHCP Distribution
|
||||
Version 3.0.1
|
||||
Release Candidate 10
|
||||
Release Candidate 12
|
||||
June, 2002
|
||||
|
||||
Release Notes
|
||||
@ -46,6 +46,53 @@ Murrell at BC Tel Advanced Communications. I'd like to express my
|
||||
thanks to all of these good people here, both for working on the code
|
||||
and for prodding me into improving it.
|
||||
|
||||
Changes since 3.0.1rc11
|
||||
|
||||
- A patch from Steve Campbell was applied with minor modifications to
|
||||
permit reverse dns PTR record updates with values containing spaces.
|
||||
|
||||
- A patch from Florian Lohoff was applied with some modifications to
|
||||
dhcrelay. It now discards packets whose hop count exceeds 10 by default,
|
||||
and a command-line option (-c) can be used to set this threshold.
|
||||
|
||||
- A failover bug relating to identifying peers by name length instead of
|
||||
by name was fixed.
|
||||
|
||||
- Delcaring failover configs within shared-network statements should no
|
||||
longer result in error.
|
||||
|
||||
- The -nw command line option to dhclient now works.
|
||||
|
||||
- Thanks to a patch from Michael Richardson:
|
||||
- Some problems with long option processing have been fixed.
|
||||
- Some fixes to minires so that updates of KEY records will work.
|
||||
|
||||
- contrib/ms2isc was updated by Shu-Min Chang of the Intel Corporation.
|
||||
see contrib/ms2isc/readme.txt for revision notes.
|
||||
|
||||
- Dhclient no longer uses shell commands to kill another instance of
|
||||
itself, it sends the signal directly. Thanks to a patch from Martin
|
||||
Blapp.
|
||||
|
||||
- The FreeBSD dhclient-script was changed so that a failure to write to
|
||||
/etc/resolv.conf does not prematurely end the script. This keeps dhclient
|
||||
from looping infinitely when this is the case. Thanks to a patch from
|
||||
Martin Blapp.
|
||||
|
||||
- A patch from Bill Stephens was applied which resolves a problem with lease
|
||||
expiry times in failover configurations.
|
||||
|
||||
- A memory leak in configuration parsing was closed thanks to a patch from
|
||||
Steve G.
|
||||
|
||||
- The function which discovers interfaces will now skip non-broadcast or
|
||||
point-to-point interfaces, thanks to a patch from David Brownlee.
|
||||
|
||||
- Options not yet known by the dhcpd or dhclient have had their names
|
||||
changed such that they do not contain # symbols, in case they should ever
|
||||
appear in a lease file. An option that might have been named "#144" is
|
||||
now "unknown-144".
|
||||
|
||||
Changes since 3.0.1rc10
|
||||
|
||||
- Potential buffer overflows in minires repaired.
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: discover.c,v 1.42.2.13 2002/11/17 02:26:57 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: discover.c,v 1.42.2.14 2003/07/25 19:44:15 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -258,10 +258,12 @@ void discover_interfaces (state)
|
||||
if (!strcmp (tmp -> name, ifp -> ifr_name))
|
||||
break;
|
||||
|
||||
/* Skip loopback, point-to-point and down interfaces,
|
||||
except don't skip down interfaces if we're trying to
|
||||
get a list of configurable interfaces. */
|
||||
if (((ifr.ifr_flags & IFF_LOOPBACK ||
|
||||
/* Skip non broadcast interfaces (plus loopback and
|
||||
point-to-point in case an OS incorrectly marks them
|
||||
as broadcast). Also skip down interfaces unless we're
|
||||
trying to get a list of configurable interfaces. */
|
||||
if (((!(ifr.ifr_flags & IFF_BROADCAST) ||
|
||||
ifr.ifr_flags & IFF_LOOPBACK ||
|
||||
ifr.ifr_flags & IFF_POINTOPOINT) && !tmp) ||
|
||||
(!(ifr.ifr_flags & IFF_UP) &&
|
||||
state != DISCOVER_UNCONFIGURED))
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: options.c,v 1.85.2.9 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: options.c,v 1.85.2.12 2003/03/31 03:06:55 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#define DHCP_OPTION_DATA
|
||||
@ -166,15 +166,36 @@ int parse_option_buffer (options, buffer, length, universe)
|
||||
the parse fails, or the option isn't an encapsulation (by
|
||||
far the most common case), or the option isn't entirely
|
||||
an encapsulation, keep the raw data as well. */
|
||||
if (!((universe -> options [code] -> format [0] == 'e' ||
|
||||
if (universe -> options [code] &&
|
||||
!((universe -> options [code] -> format [0] == 'e' ||
|
||||
universe -> options [code] -> format [0] == 'E') &&
|
||||
(parse_encapsulated_suboptions
|
||||
(options, universe -> options [code],
|
||||
buffer + offset + 2, len,
|
||||
universe, (const char *)0)))) {
|
||||
save_option_buffer (universe, options, bp,
|
||||
&bp -> data [offset + 2], len,
|
||||
universe -> options [code], 1);
|
||||
op = lookup_option (universe, options, code);
|
||||
if (op) {
|
||||
struct data_string new;
|
||||
memset (&new, 0, sizeof new);
|
||||
if (!buffer_allocate (&new.buffer, op -> data.len + len,
|
||||
MDL)) {
|
||||
log_error ("parse_option_buffer: No memory.");
|
||||
return 0;
|
||||
}
|
||||
memcpy (new.buffer -> data, op -> data.data,
|
||||
op -> data.len);
|
||||
memcpy (&new.buffer -> data [op -> data.len],
|
||||
&bp -> data [offset + 2], len);
|
||||
new.len = op -> data.len + len;
|
||||
new.data = new.buffer -> data;
|
||||
data_string_forget (&op -> data, MDL);
|
||||
data_string_copy (&op -> data, &new, MDL);
|
||||
data_string_forget (&new, MDL);
|
||||
} else {
|
||||
save_option_buffer (universe, options, bp,
|
||||
&bp -> data [offset + 2], len,
|
||||
universe -> options [code], 1);
|
||||
}
|
||||
}
|
||||
offset += len + 2;
|
||||
}
|
||||
@ -470,14 +491,18 @@ int cons_options (inpacket, outpacket, lease, client_state,
|
||||
and no alternate maximum message size has been specified, take the
|
||||
one in the packet. */
|
||||
|
||||
if (!mms && inpacket &&
|
||||
if (inpacket &&
|
||||
(op = lookup_option (&dhcp_universe, inpacket -> options,
|
||||
DHO_DHCP_MAX_MESSAGE_SIZE))) {
|
||||
evaluate_option_cache (&ds, inpacket,
|
||||
lease, client_state, in_options,
|
||||
cfg_options, scope, op, MDL);
|
||||
if (ds.len >= sizeof (u_int16_t))
|
||||
mms = getUShort (ds.data);
|
||||
if (ds.len >= sizeof (u_int16_t)) {
|
||||
i = getUShort (ds.data);
|
||||
|
||||
if(!mms || (i < mms))
|
||||
mms = i;
|
||||
}
|
||||
data_string_forget (&ds, MDL);
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: parse.c,v 1.104.2.12 2002/11/17 02:58:34 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: parse.c,v 1.104.2.14 2003/07/25 19:36:11 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -284,8 +284,11 @@ int parse_ip_addr_or_hostname (expr, cfile, uniform)
|
||||
name = parse_host_name (cfile);
|
||||
if (!name)
|
||||
return 0;
|
||||
if (!make_host_lookup (expr, name))
|
||||
if (!make_host_lookup (expr, name)) {
|
||||
dfree(name, MDL);
|
||||
return 0;
|
||||
}
|
||||
dfree(name, MDL);
|
||||
if (!uniform) {
|
||||
if (!make_limit (&x, *expr, 4))
|
||||
return 0;
|
||||
@ -4040,7 +4043,11 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
||||
}
|
||||
|
||||
if (binop != expr_none) {
|
||||
if (expression_context (rhs) != expression_context (lhs)) {
|
||||
rhs_context = expression_context(rhs);
|
||||
lhs_context = expression_context(lhs);
|
||||
|
||||
if ((rhs_context != context_any) && (lhs_context != context_any) &&
|
||||
(rhs_context != lhs_context)) {
|
||||
parse_warn (cfile, "illegal expression relating different types");
|
||||
skip_to_semi (cfile);
|
||||
expression_dereference (&rhs, MDL);
|
||||
@ -4052,9 +4059,10 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
||||
switch(binop) {
|
||||
case expr_not_equal:
|
||||
case expr_equal:
|
||||
if ((expression_context(rhs) != context_data_or_numeric) &&
|
||||
(expression_context(rhs) != context_data) &&
|
||||
(expression_context(rhs) != context_numeric)) {
|
||||
if ((rhs_context != context_data_or_numeric) &&
|
||||
(rhs_context != context_data) &&
|
||||
(rhs_context != context_numeric) &&
|
||||
(rhs_context != context_any)) {
|
||||
parse_warn (cfile, "expecting data/numeric expression");
|
||||
skip_to_semi (cfile);
|
||||
expression_dereference (&rhs, MDL);
|
||||
@ -4065,7 +4073,8 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
||||
|
||||
case expr_and:
|
||||
case expr_or:
|
||||
if (expression_context(rhs) != context_boolean) {
|
||||
if ((rhs_context != context_boolean) &&
|
||||
(rhs_context != context_any)) {
|
||||
parse_warn (cfile, "expecting boolean expressions");
|
||||
skip_to_semi (cfile);
|
||||
expression_dereference (&rhs, MDL);
|
||||
@ -4082,7 +4091,8 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
||||
case expr_binary_and:
|
||||
case expr_binary_or:
|
||||
case expr_binary_xor:
|
||||
if (expression_context(rhs) != context_numeric) {
|
||||
if ((rhs_context != context_numeric) &&
|
||||
(rhs_context != context_any)) {
|
||||
parse_warn (cfile, "expecting numeric expressions");
|
||||
skip_to_semi (cfile);
|
||||
expression_dereference (&rhs, MDL);
|
||||
|
@ -3,7 +3,7 @@
|
||||
Turn data structures into printable text. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995-2002 Internet Software Consortium.
|
||||
* Copyright (c) 1995-2003 Internet Software Consortium.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: print.c,v 1.53.2.7 2002/11/17 02:26:59 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
|
||||
"$Id: print.c,v 1.53.2.9 2003/03/31 03:06:56 dhankins Exp $ Copyright (c) 1995-2003 The Internet Software Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -223,7 +223,7 @@ void print_lease (lease)
|
||||
lease -> host ? lease -> host -> name : "<none>");
|
||||
}
|
||||
|
||||
#if defined (DEBUG)
|
||||
#if defined (DEBUG_PACKET)
|
||||
void dump_packet_option (struct option_cache *oc,
|
||||
struct packet *packet,
|
||||
struct lease *lease,
|
||||
@ -304,19 +304,46 @@ void dump_raw (buf, len)
|
||||
char lbuf [80];
|
||||
int lbix = 0;
|
||||
|
||||
lbuf [0] = 0;
|
||||
/*
|
||||
1 2 3 4 5 6 7
|
||||
01234567890123456789012345678901234567890123456789012345678901234567890123
|
||||
280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .................
|
||||
*/
|
||||
|
||||
memset(lbuf, ' ', 79);
|
||||
lbuf [79] = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i & 15) == 0) {
|
||||
if (lbix)
|
||||
log_info (lbuf);
|
||||
sprintf (lbuf, "%03x:", i);
|
||||
lbix = 4;
|
||||
if (lbix) {
|
||||
lbuf[53]=' ';
|
||||
lbuf[54]=' ';
|
||||
lbuf[55]=' ';
|
||||
lbuf[73]='\0';
|
||||
log_info (lbuf);
|
||||
}
|
||||
memset(lbuf, ' ', 79);
|
||||
lbuf [79] = 0;
|
||||
sprintf (lbuf, "%03x:", i);
|
||||
lbix = 4;
|
||||
} else if ((i & 7) == 0)
|
||||
lbuf [lbix++] = ' ';
|
||||
|
||||
if(isprint(buf[i])) {
|
||||
lbuf[56+(i%16)]=buf[i];
|
||||
} else {
|
||||
lbuf[56+(i%16)]='.';
|
||||
}
|
||||
|
||||
sprintf (&lbuf [lbix], " %02x", buf [i]);
|
||||
lbix += 3;
|
||||
lbuf[lbix]=' ';
|
||||
|
||||
}
|
||||
lbuf[53]=' ';
|
||||
lbuf[54]=' ';
|
||||
lbuf[55]=' ';
|
||||
lbuf[73]='\0';
|
||||
log_info (lbuf);
|
||||
}
|
||||
|
||||
@ -337,7 +364,7 @@ void hash_dump (table)
|
||||
if (bp -> len)
|
||||
dump_raw (bp -> name, bp -> len);
|
||||
else
|
||||
log_info ((const char *)bp -> name);
|
||||
log_info ("%s", (const char *)bp -> name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1248,6 +1275,9 @@ void print_dns_status (int status, ns_updque *uq)
|
||||
case T_TXT:
|
||||
en = "TXT";
|
||||
break;
|
||||
case T_KEY:
|
||||
en = "KEY";
|
||||
break;
|
||||
case T_CNAME:
|
||||
en = "CNAME";
|
||||
break;
|
||||
@ -1268,13 +1298,19 @@ void print_dns_status (int status, ns_updque *uq)
|
||||
if (s + 1 < end)
|
||||
*s++ = '"';
|
||||
}
|
||||
if (s + u -> r_size < end) {
|
||||
memcpy (s, u -> r_data, u -> r_size);
|
||||
s += u -> r_size;
|
||||
if (u -> r_type == T_TXT) {
|
||||
if (s + 1 < end)
|
||||
*s++ = '"';
|
||||
}
|
||||
if(u->r_type == T_KEY) {
|
||||
strcat(s, "<keydata>");
|
||||
s+=strlen("<keydata>");
|
||||
}
|
||||
else {
|
||||
if (s + u -> r_size < end) {
|
||||
memcpy (s, u -> r_data, u -> r_size);
|
||||
s += u -> r_size;
|
||||
if (u -> r_type == T_TXT) {
|
||||
if (s + 1 < end)
|
||||
*s++ = '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (position) {
|
||||
|
@ -1,3 +1,3 @@
|
||||
/* Current version of ISC DHCP Distribution. */
|
||||
|
||||
#define DHCP_VERSION "V3.0.1rc11"
|
||||
#define DHCP_VERSION "V3.0.1rc12"
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
#if !defined(lint) && !defined(SABER)
|
||||
static const char rcsid[] = "$Id: res_mkupdate.c,v 1.7 2001/01/11 02:16:24 mellon Exp $";
|
||||
static const char rcsid[] = "$Id: res_mkupdate.c,v 1.7.2.2 2003/05/19 00:33:22 dhankins Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -52,6 +52,7 @@ static int gethexnum_str(const u_char **, const u_char *);
|
||||
static int getword_str(char *, int,
|
||||
const unsigned char **,
|
||||
const unsigned char *);
|
||||
static int getphrase_str(char *, int, const u_char **, const u_char *);
|
||||
static int getstr_str(char *, int, const u_char **, const u_char *);
|
||||
|
||||
struct valuelist {
|
||||
@ -101,7 +102,8 @@ res_nmkupdate(res_state statp,
|
||||
u_int16_t rtype, rclass;
|
||||
u_int32_t n1, rttl;
|
||||
u_char *dnptrs[20], **dpp, **lastdnptr;
|
||||
unsigned siglen, keylen, certlen;
|
||||
unsigned siglen, certlen;
|
||||
int keylen;
|
||||
unsigned buflen = *blp;
|
||||
u_char *buf = (unsigned char *)bp;
|
||||
|
||||
@ -234,7 +236,7 @@ res_nmkupdate(res_state statp,
|
||||
case T_MR:
|
||||
case T_NS:
|
||||
case T_PTR:
|
||||
if (!getword_str(buf2, sizeof buf2, &startp, endp))
|
||||
if (!getphrase_str(buf2, sizeof buf2, &startp, endp))
|
||||
return (-1);
|
||||
n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
|
||||
if (n < 0)
|
||||
@ -549,36 +551,6 @@ res_nmkupdate(res_state statp,
|
||||
cp += siglen;
|
||||
break;
|
||||
}
|
||||
case ns_t_key:
|
||||
/* flags */
|
||||
n = gethexnum_str(&startp, endp);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
ShrinkBuffer(INT16SZ);
|
||||
PUTSHORT(n, cp);
|
||||
/* proto */
|
||||
n = getnum_str(&startp, endp);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
ShrinkBuffer(1);
|
||||
*cp++ = n;
|
||||
/* alg */
|
||||
n = getnum_str(&startp, endp);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
ShrinkBuffer(1);
|
||||
*cp++ = n;
|
||||
/* key */
|
||||
if ((n = getword_str(buf2, sizeof buf2,
|
||||
&startp, endp)) < 0)
|
||||
return (-1);
|
||||
keylen = b64_pton(buf2, buf3, sizeof(buf3));
|
||||
if (keylen < 0)
|
||||
return (-1);
|
||||
ShrinkBuffer(keylen);
|
||||
memcpy(cp, buf3, keylen);
|
||||
cp += keylen;
|
||||
break;
|
||||
case ns_t_nxt:
|
||||
{
|
||||
int success, nxt_type;
|
||||
@ -613,6 +585,38 @@ res_nmkupdate(res_state statp,
|
||||
cp += n;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
case ns_t_key:
|
||||
/* flags */
|
||||
n = gethexnum_str(&startp, endp);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
ShrinkBuffer(INT16SZ);
|
||||
PUTSHORT(n, cp);
|
||||
/* proto */
|
||||
n = getnum_str(&startp, endp);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
ShrinkBuffer(1);
|
||||
*cp++ = n;
|
||||
/* alg */
|
||||
n = getnum_str(&startp, endp);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
ShrinkBuffer(1);
|
||||
*cp++ = n;
|
||||
/* key */
|
||||
if ((n = getword_str(buf2, sizeof buf2,
|
||||
&startp, endp)) < 0)
|
||||
return (-1);
|
||||
keylen = b64_pton(buf2, buf3, sizeof(buf3));
|
||||
if (keylen < 0)
|
||||
return (-1);
|
||||
ShrinkBuffer(keylen);
|
||||
memcpy(cp, buf3, keylen);
|
||||
cp += keylen;
|
||||
break;
|
||||
case ns_t_cert:
|
||||
/* type */
|
||||
n = getnum_str(&startp, endp);
|
||||
@ -645,6 +649,8 @@ res_nmkupdate(res_state statp,
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "NSupdate of RR type: %d not implemented\n",
|
||||
rrecp->r_type);
|
||||
return (-1);
|
||||
} /*switch*/
|
||||
n = (u_int16_t)((cp - sp2) - INT16SZ);
|
||||
@ -688,6 +694,35 @@ getword_str(char *buf, int size, const u_char **startpp, const u_char *endp) {
|
||||
return (cp != buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a phrase - possibly containing blanks - from a string (not file)
|
||||
* into buf. modify the start pointer to point after the
|
||||
* phrase in the string.
|
||||
*/
|
||||
static int
|
||||
getphrase_str(char *buf, int size, const u_char **startpp, const u_char *endp) {
|
||||
char *cp;
|
||||
int c;
|
||||
|
||||
for (cp = buf; *startpp <= endp; ) {
|
||||
c = **startpp;
|
||||
if (isspace(c) && cp == buf ) {
|
||||
/* leading whitespace */
|
||||
(*startpp)++;
|
||||
continue;
|
||||
}
|
||||
else if ( c == '\0' ) {
|
||||
break;
|
||||
}
|
||||
(*startpp)++;
|
||||
if (cp >= buf+size-1)
|
||||
break;
|
||||
*cp++ = (u_char)c;
|
||||
}
|
||||
*cp = '\0';
|
||||
return (cp != buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* get a white spae delimited string from memory. Process quoted strings
|
||||
* and \DDD escapes. Return length or -1 on error. Returned string may
|
||||
|
@ -119,7 +119,10 @@ static const char *text[ISC_R_NRESULTS] = {
|
||||
|
||||
const char *isc_result_totext (isc_result_t result)
|
||||
{
|
||||
static char ebuf[40];
|
||||
|
||||
if (result >= ISC_R_SUCCESS && result < ISC_R_NRESULTS)
|
||||
return text [result];
|
||||
return "unknown error.";
|
||||
sprintf(ebuf, "unknown error: %d", result);
|
||||
return ebuf;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user