/*
* 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.
*/
/*! \file
* \brief
* Based on the Dynamic DNS reference implementation by Viraj Bais
* <viraj_bais@ccm.fm.intel.com>
*/
#endif /* not lint */
#include "port_before.h"
#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <resolv.h>
#include <res_update.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "port_after.h"
/* Options. Leave them on. */
#define DEBUG
/* Forward. */
int res_protocolnumber(const char *);
int res_servicenumber(const char *);
/*%
* Form update packets.
* Returns the size of the resulting packet if no error
*
* On error,
* returns
* portion for update packets
*\li -2 if length of buffer passed is insufficient
*\li -3 if zone section is not the first section in
* the linked list, or section order has a problem
*\li -4 on a number overflow
*\li -5 unknown operation or no records
*/
int
/*
* Initialize header fields.
*/
return (-1);
if (rrecp_start == NULL)
return (-5);
return (-3);
numrrs++;
return (-1);
if (counts[i])
return (-3);
/* overload class and type */
rttl = 0;
case YXDOMAIN:
break;
case NXDOMAIN:
break;
case NXRRSET:
break;
case YXRRSET:
break;
default:
"res_mkupdate: incorrect opcode: %d\n",
return (-1);
}
case DELETE:
break;
case ADD:
break;
default:
"res_mkupdate: incorrect opcode: %d\n",
return (-1);
}
}
/*
* XXX appending default domain to owner name is omitted,
* fqdn must be provided
*/
lastdnptr)) < 0)
return (-1);
cp += n;
return (-3);
continue;
}
return (-1);
else {
continue;
}
}
/* XXX this should be done centrally. */
case T_A:
return (-1);
return (-1);
break;
case T_CNAME:
case T_MB:
case T_MG:
case T_MR:
case T_NS:
case T_PTR:
case ns_t_dname:
return (-1);
if (n < 0)
return (-1);
cp += n;
ShrinkBuffer(n);
break;
case T_MINFO:
case T_SOA:
case T_RP:
for (i = 0; i < 2; i++) {
endp))
return (-1);
if (n < 0)
return (-1);
cp += n;
ShrinkBuffer(n);
}
startp++;
if (*startp == '(') {
multiline = 1;
startp++;
} else
multiline = 0;
/* serial, refresh, retry, expire, minimum */
for (i = 0; i < 5; i++) {
if (soanum < 0)
return (-1);
}
if (multiline) {
startp++;
if (*startp != ')')
return (-1);
}
}
break;
case T_MX:
case T_AFSDB:
case T_RT:
if (n < 0)
return (-1);
return (-1);
if (n < 0)
return (-1);
cp += n;
ShrinkBuffer(n);
break;
case T_SRV:
if (n < 0)
return (-1);
if (n < 0)
return (-1);
if (n < 0)
return (-1);
return (-1);
if (n < 0)
return (-1);
cp += n;
ShrinkBuffer(n);
break;
case T_PX:
if (n < 0)
return (-1);
for (i = 0; i < 2; i++) {
endp))
return (-1);
if (n < 0)
return (-1);
cp += n;
ShrinkBuffer(n);
}
break;
case T_WKS: {
unsigned int maxbm = 0;
return (-1);
return (-1);
return (-1);
if ((i = res_protocolnumber(buf2)) < 0)
return (-1);
ShrinkBuffer(1);
*cp++ = i & 0xff;
for (i = 0; i < MAXPORT/8 ; i++)
bm[i] = 0;
if ((n = res_servicenumber(buf2)) <= 0)
return (-1);
if (n < MAXPORT) {
if ((unsigned)n > maxbm)
maxbm = n;
} else
return (-1);
}
break;
}
case T_HINFO:
for (i = 0; i < 2; i++) {
return (-1);
if (n > 255)
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
cp += n;
}
break;
case T_TXT:
for (;;) {
break;
return (-1);
}
if (n > 255)
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
cp += n;
}
break;
case T_X25:
/* RFC1183 */
endp)) < 0)
return (-1);
if (n > 255)
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
cp += n;
break;
case T_ISDN:
/* RFC1183 */
endp)) < 0)
return (-1);
if ((n > 255) || (n == 0))
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
cp += n;
endp)) < 0)
n = 0;
if (n > 255)
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
cp += n;
break;
case T_NSAP:
ShrinkBuffer(n);
cp += n;
} else {
return (-1);
}
break;
case T_LOC:
ShrinkBuffer(n);
cp += n;
} else
return (-1);
break;
case ns_t_sig:
{
/* type */
return (-1);
return (-1);
/* alg */
if (n < 0)
return (-1);
ShrinkBuffer(1);
*cp++ = n;
/* labels */
if (n <= 0 || n > 255)
return (-1);
ShrinkBuffer(1);
*cp++ = n;
/* ottl & expire */
return (-1);
if (!dateerror) {
}
else {
char *ulendp;
errno = 0;
if (errno != 0 ||
return (-1);
endp))
return (-1);
if (dateerror)
return (-1);
}
/* expire */
/* timesigned */
return (-1);
if (!dateerror) {
}
else
return (-1);
/* footprint */
if (n < 0)
return (-1);
/* signer name */
return (-1);
if (n < 0)
return (-1);
cp += n;
ShrinkBuffer(n);
/* sig */
return (-1);
if (siglen < 0)
return (-1);
break;
}
case ns_t_key:
/* flags */
if (n < 0)
return (-1);
/* proto */
if (n < 0)
return (-1);
ShrinkBuffer(1);
*cp++ = n;
/* alg */
if (n < 0)
return (-1);
ShrinkBuffer(1);
*cp++ = n;
/* key */
return (-1);
if (keylen < 0)
return (-1);
break;
case ns_t_nxt:
{
int maxtype;
/* next name */
return (-1);
if (n < 0)
return (-1);
cp += n;
ShrinkBuffer(n);
maxtype = 0;
for (;;) {
endp))
break;
&success);
return (-1);
}
ShrinkBuffer(n);
cp += n;
break;
}
case ns_t_cert:
/* type */
if (n < 0)
return (-1);
/* key tag */
if (n < 0)
return (-1);
/* alg */
if (n < 0)
return (-1);
ShrinkBuffer(1);
*cp++ = n;
/* cert */
return (-1);
if (certlen < 0)
return (-1);
break;
case ns_t_aaaa:
return (-1);
return (-1);
cp += NS_IN6ADDRSZ;
break;
case ns_t_naptr:
/* Order Preference Flags Service Replacement Regexp */
/* Order */
if (n < 0 || n > 65535)
return (-1);
/* Preference */
if (n < 0 || n > 65535)
return (-1);
/* Flags */
return (-1);
}
if (n > 255)
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
cp += n;
/* Service Classes */
return (-1);
}
if (n > 255)
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
cp += n;
/* Pattern */
return (-1);
}
if (n > 255)
return (-1);
ShrinkBuffer(n+1);
*cp++ = n;
cp += n;
/* Replacement */
return (-1);
if (n < 0)
return (-1);
cp += n;
ShrinkBuffer(n);
break;
default:
return (-1);
} /*switch*/
} /*for*/
}
/*%
* Get a whitespace delimited word from a string (not file)
* into buf. modify the start pointer to point after the
* word in the string.
*/
static int
char *cp;
int c;
c = **startpp;
if (isspace(c) || c == '\0') {
break;
else { /*%< leading whitespace */
(*startpp)++;
continue;
}
}
(*startpp)++;
break;
}
*cp = '\0';
}
/*%
* get a white spae delimited string from memory. Process quoted strings
* and \\DDD escapes. Return length or -1 on error. Returned string may
* contain nulls.
*/
static int
char *cp;
int c, c1 = 0;
int inquote = 0;
int seen_quote = 0;
int escape = 0;
int dig = 0;
if ((c = **startpp) == '\0')
break;
/* leading white space */
(*startpp)++;
continue;
}
switch (c) {
case '\\':
if (!escape) {
escape = 1;
dig = 0;
c1 = 0;
(*startpp)++;
continue;
}
goto do_escape;
case '"':
if (!escape) {
seen_quote = 1;
(*startpp)++;
continue;
}
/* fall through */
default:
if (escape) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (++dig == 3) {
c = c1 &0xff;
break;
}
(*startpp)++;
continue;
}
escape = 0;
goto done;
goto done;
(*startpp)++;
}
}
done:
*cp = '\0';
}
/*%
* Get a whitespace delimited base 16 number from a string (not file) into buf
* update the start pointer to point after the number in the string.
*/
static int
int c, n;
int seendigit = 0;
int m = 0;
(*startpp)+=2;
c = **startpp;
if (isspace(c) || c == '\0') {
if (seendigit) /*%< trailing whitespace */
break;
else { /*%< leading whitespace */
(*startpp)++;
continue;
}
}
if (c == ';') {
((c = **startpp) != '\n'))
(*startpp)++;
if (seendigit)
break;
continue;
}
if (!isxdigit(c)) {
if (c == ')' && seendigit) {
(*startpp)--;
break;
}
return (-1);
}
(*startpp)++;
if (isdigit(c))
n = n * 16 + (c - '0');
else
seendigit = 1;
}
return (n + m);
}
/*%
* Get a whitespace delimited base 10 number from a string (not file) into buf
* update the start pointer to point after the number in the string.
*/
static int
int c, n;
int seendigit = 0;
int m = 0;
c = **startpp;
if (isspace(c) || c == '\0') {
if (seendigit) /*%< trailing whitespace */
break;
else { /*%< leading whitespace */
(*startpp)++;
continue;
}
}
if (c == ';') {
((c = **startpp) != '\n'))
(*startpp)++;
if (seendigit)
break;
continue;
}
if (!isdigit(c)) {
if (c == ')' && seendigit) {
(*startpp)--;
break;
}
return (-1);
}
(*startpp)++;
n = n * 10 + (c - '0');
seendigit = 1;
}
return (n + m);
}
/*%
* Allocate a resource record buffer & save rr info.
*/
if (rrecp)
return (NULL);
}
return (rrecp);
}
/*%
* Free a resource record buffer created by res_mkupdrec.
*/
void
/* Note: freeing r_dp is the caller's responsibility. */
}
struct valuelist {
char * name;
char * proto;
int port;
};
static void
#ifdef MAYBE_HESIOD
setservent(0);
#else
setservent(1);
#endif
if (!slp)
break;
break;
}
if (servicelist)
servicelist = slp;
}
endservent();
}
void
}
servicelist = (struct valuelist *)0;
}
void
res_buildprotolist(void) {
#ifdef MAYBE_HESIOD
setprotoent(0);
#else
setprotoent(1);
#endif
if (!slp)
break;
break;
}
if (protolist)
}
endprotoent();
}
void
res_destroyprotolist(void) {
}
}
static int
int n;
}
}
n = -1;
return (n);
}
/*%
* Convert service name or (ascii) number to int.
*/
int
res_servicenumber(const char *p) {
if (servicelist == (struct valuelist *)0)
return (findservice(p, &servicelist));
}
/*%
* Convert protocol name or (ascii) number to int.
*/
int
res_protocolnumber(const char *p) {
return (findservice(p, &protolist));
}
static struct servent *
continue;
}
return (&serv);
}
}
return (0);
}
static struct protoent *
}
return (&prot);
}
return (0);
}
const char *
if (pp == 0) {
return (number);
}
}
const char *
if (servicelist == (struct valuelist *)0)
if (ss == 0) {
return (number);
}
}