source: rtems-libbsd/freebsd/lib/libc/resolv/res_mkupdate.c @ d48955b

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since d48955b was d48955b, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/13 at 08:02:16

Add and use <machine/rtems-bsd-user-space.h>

  • Property mode set to 100644
File size: 26.8 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996-1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/*! \file
21 * \brief
22 * Based on the Dynamic DNS reference implementation by Viraj Bais
23 * &lt;viraj_bais@ccm.fm.intel.com>
24 */
25
26#if !defined(lint) && !defined(SABER)
27static const char rcsid[] = "$Id: res_mkupdate.c,v 1.4.18.4 2005/10/14 05:44:12 marka Exp $";
28#endif /* not lint */
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include "port_before.h"
33
34#include <rtems/bsd/sys/types.h>
35#include <rtems/bsd/sys/param.h>
36
37#include <netinet/in.h>
38#include <arpa/nameser.h>
39#include <arpa/inet.h>
40
41#include <errno.h>
42#include <limits.h>
43#include <netdb.h>
44#include <resolv.h>
45#include <res_update.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
50#include <ctype.h>
51
52#ifdef _LIBC
53#include <isc/list.h>
54#endif
55
56#include "port_after.h"
57
58/* Options.  Leave them on. */
59#define DEBUG
60#define MAXPORT 1024
61
62static int getnum_str(u_char **, u_char *);
63static int gethexnum_str(u_char **, u_char *);
64static int getword_str(char *, int, u_char **, u_char *);
65static int getstr_str(char *, int, u_char **, u_char *);
66
67#define ShrinkBuffer(x)  if ((buflen -= x) < 0) return (-2);
68
69/* Forward. */
70
71#ifdef _LIBC
72static
73#endif
74int res_protocolnumber(const char *);
75#ifdef _LIBC
76static
77#endif
78int res_servicenumber(const char *);
79
80/*%
81 * Form update packets.
82 * Returns the size of the resulting packet if no error
83 *
84 * On error,
85 *      returns
86 *\li              -1 if error in reading a word/number in rdata
87 *                 portion for update packets
88 *\li           -2 if length of buffer passed is insufficient
89 *\li           -3 if zone section is not the first section in
90 *                 the linked list, or section order has a problem
91 *\li           -4 on a number overflow
92 *\li           -5 unknown operation or no records
93 */
94int
95res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) {
96        ns_updrec *rrecp_start = rrecp_in;
97        HEADER *hp;
98        u_char *cp, *sp2, *startp, *endp;
99        int n, i, soanum, multiline;
100        ns_updrec *rrecp;
101        struct in_addr ina;
102        struct in6_addr in6a;
103        char buf2[MAXDNAME];
104        u_char buf3[MAXDNAME];
105        int section, numrrs = 0, counts[ns_s_max];
106        u_int16_t rtype, rclass;
107        u_int32_t n1, rttl;
108        u_char *dnptrs[20], **dpp, **lastdnptr;
109#ifndef _LIBC
110        int siglen;
111#endif
112        int keylen, certlen;
113
114        /*
115         * Initialize header fields.
116         */
117        if ((buf == NULL) || (buflen < HFIXEDSZ))
118                return (-1);
119        memset(buf, 0, HFIXEDSZ);
120        hp = (HEADER *) buf;
121        hp->id = htons(++statp->id);
122        hp->opcode = ns_o_update;
123        hp->rcode = NOERROR;
124        cp = buf + HFIXEDSZ;
125        buflen -= HFIXEDSZ;
126        dpp = dnptrs;
127        *dpp++ = buf;
128        *dpp++ = NULL;
129        lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
130
131        if (rrecp_start == NULL)
132                return (-5);
133        else if (rrecp_start->r_section != S_ZONE)
134                return (-3);
135
136        memset(counts, 0, sizeof counts);
137        for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) {
138                numrrs++;
139                section = rrecp->r_section;
140                if (section < 0 || section >= ns_s_max)
141                        return (-1);
142                counts[section]++;
143                for (i = section + 1; i < ns_s_max; i++)
144                        if (counts[i])
145                                return (-3);
146                rtype = rrecp->r_type;
147                rclass = rrecp->r_class;
148                rttl = rrecp->r_ttl;
149                /* overload class and type */
150                if (section == S_PREREQ) {
151                        rttl = 0;
152                        switch (rrecp->r_opcode) {
153                        case YXDOMAIN:
154                                rclass = C_ANY;
155                                rtype = T_ANY;
156                                rrecp->r_size = 0;
157                                break;
158                        case NXDOMAIN:
159                                rclass = C_NONE;
160                                rtype = T_ANY;
161                                rrecp->r_size = 0;
162                                break;
163                        case NXRRSET:
164                                rclass = C_NONE;
165                                rrecp->r_size = 0;
166                                break;
167                        case YXRRSET:
168                                if (rrecp->r_size == 0)
169                                        rclass = C_ANY;
170                                break;
171                        default:
172                                fprintf(stderr,
173                                        "res_mkupdate: incorrect opcode: %d\n",
174                                        rrecp->r_opcode);
175                                fflush(stderr);
176                                return (-1);
177                        }
178                } else if (section == S_UPDATE) {
179                        switch (rrecp->r_opcode) {
180                        case DELETE:
181                                rclass = rrecp->r_size == 0 ? C_ANY : C_NONE;
182                                break;
183                        case ADD:
184                                break;
185                        default:
186                                fprintf(stderr,
187                                        "res_mkupdate: incorrect opcode: %d\n",
188                                        rrecp->r_opcode);
189                                fflush(stderr);
190                                return (-1);
191                        }
192                }
193
194                /*
195                 * XXX  appending default domain to owner name is omitted,
196                 *      fqdn must be provided
197                 */
198                if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs,
199                                 lastdnptr)) < 0)
200                        return (-1);
201                cp += n;
202                ShrinkBuffer(n + 2*INT16SZ);
203                PUTSHORT(rtype, cp);
204                PUTSHORT(rclass, cp);
205                if (section == S_ZONE) {
206                        if (numrrs != 1 || rrecp->r_type != T_SOA)
207                                return (-3);
208                        continue;
209                }
210                ShrinkBuffer(INT32SZ + INT16SZ);
211                PUTLONG(rttl, cp);
212                sp2 = cp;  /*%< save pointer to length byte */
213                cp += INT16SZ;
214                if (rrecp->r_size == 0) {
215                        if (section == S_UPDATE && rclass != C_ANY)
216                                return (-1);
217                        else {
218                                PUTSHORT(0, sp2);
219                                continue;
220                        }
221                }
222                startp = rrecp->r_data;
223                endp = startp + rrecp->r_size - 1;
224                /* XXX this should be done centrally. */
225                switch (rrecp->r_type) {
226                case T_A:
227                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
228                                return (-1);
229                        if (!inet_aton(buf2, &ina))
230                                return (-1);
231                        n1 = ntohl(ina.s_addr);
232                        ShrinkBuffer(INT32SZ);
233                        PUTLONG(n1, cp);
234                        break;
235                case T_CNAME:
236                case T_MB:
237                case T_MG:
238                case T_MR:
239                case T_NS:
240                case T_PTR:
241                case ns_t_dname:
242                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
243                                return (-1);
244                        n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
245                        if (n < 0)
246                                return (-1);
247                        cp += n;
248                        ShrinkBuffer(n);
249                        break;
250                case T_MINFO:
251                case T_SOA:
252                case T_RP:
253                        for (i = 0; i < 2; i++) {
254                                if (!getword_str(buf2, sizeof buf2, &startp,
255                                                 endp))
256                                return (-1);
257                                n = dn_comp(buf2, cp, buflen,
258                                            dnptrs, lastdnptr);
259                                if (n < 0)
260                                        return (-1);
261                                cp += n;
262                                ShrinkBuffer(n);
263                        }
264                        if (rrecp->r_type == T_SOA) {
265                                ShrinkBuffer(5 * INT32SZ);
266                                while (isspace(*startp) || !*startp)
267                                        startp++;
268                                if (*startp == '(') {
269                                        multiline = 1;
270                                        startp++;
271                                } else
272                                        multiline = 0;
273                                /* serial, refresh, retry, expire, minimum */
274                                for (i = 0; i < 5; i++) {
275                                        soanum = getnum_str(&startp, endp);
276                                        if (soanum < 0)
277                                                return (-1);
278                                        PUTLONG(soanum, cp);
279                                }
280                                if (multiline) {
281                                        while (isspace(*startp) || !*startp)
282                                                startp++;
283                                        if (*startp != ')')
284                                                return (-1);
285                                }
286                        }
287                        break;
288                case T_MX:
289                case T_AFSDB:
290                case T_RT:
291                        n = getnum_str(&startp, endp);
292                        if (n < 0)
293                                return (-1);
294                        ShrinkBuffer(INT16SZ);
295                        PUTSHORT(n, cp);
296                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
297                                return (-1);
298                        n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
299                        if (n < 0)
300                                return (-1);
301                        cp += n;
302                        ShrinkBuffer(n);
303                        break;
304                case T_SRV:
305                        n = getnum_str(&startp, endp);
306                        if (n < 0)
307                                return (-1);
308                        ShrinkBuffer(INT16SZ);
309                        PUTSHORT(n, cp);
310
311                        n = getnum_str(&startp, endp);
312                        if (n < 0)
313                                return (-1);
314                        ShrinkBuffer(INT16SZ);
315                        PUTSHORT(n, cp);
316
317                        n = getnum_str(&startp, endp);
318                        if (n < 0)
319                                return (-1);
320                        ShrinkBuffer(INT16SZ);
321                        PUTSHORT(n, cp);
322
323                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
324                                return (-1);
325                        n = dn_comp(buf2, cp, buflen, NULL, NULL);
326                        if (n < 0)
327                                return (-1);
328                        cp += n;
329                        ShrinkBuffer(n);
330                        break;
331                case T_PX:
332                        n = getnum_str(&startp, endp);
333                        if (n < 0)
334                                return (-1);
335                        PUTSHORT(n, cp);
336                        ShrinkBuffer(INT16SZ);
337                        for (i = 0; i < 2; i++) {
338                                if (!getword_str(buf2, sizeof buf2, &startp,
339                                                 endp))
340                                        return (-1);
341                                n = dn_comp(buf2, cp, buflen, dnptrs,
342                                            lastdnptr);
343                                if (n < 0)
344                                        return (-1);
345                                cp += n;
346                                ShrinkBuffer(n);
347                        }
348                        break;
349                case T_WKS: {
350                        char bm[MAXPORT/8];
351                        unsigned int maxbm = 0;
352
353                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
354                                return (-1);
355                        if (!inet_aton(buf2, &ina))
356                                return (-1);
357                        n1 = ntohl(ina.s_addr);
358                        ShrinkBuffer(INT32SZ);
359                        PUTLONG(n1, cp);
360
361                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
362                                return (-1);
363                        if ((i = res_protocolnumber(buf2)) < 0)
364                                return (-1);
365                        ShrinkBuffer(1);
366                        *cp++ = i & 0xff;
367                         
368                        for (i = 0; i < MAXPORT/8 ; i++)
369                                bm[i] = 0;
370
371                        while (getword_str(buf2, sizeof buf2, &startp, endp)) {
372                                if ((n = res_servicenumber(buf2)) <= 0)
373                                        return (-1);
374
375                                if (n < MAXPORT) {
376                                        bm[n/8] |= (0x80>>(n%8));
377                                        if ((unsigned)n > maxbm)
378                                                maxbm = n;
379                                } else
380                                        return (-1);
381                        }
382                        maxbm = maxbm/8 + 1;
383                        ShrinkBuffer(maxbm);
384                        memcpy(cp, bm, maxbm);
385                        cp += maxbm;
386                        break;
387                }
388                case T_HINFO:
389                        for (i = 0; i < 2; i++) {
390                                if ((n = getstr_str(buf2, sizeof buf2,
391                                                &startp, endp)) < 0)
392                                        return (-1);
393                                if (n > 255)
394                                        return (-1);
395                                ShrinkBuffer(n+1);
396                                *cp++ = n;
397                                memcpy(cp, buf2, n);
398                                cp += n;
399                        }
400                        break;
401                case T_TXT:
402                        for (;;) {
403                                if ((n = getstr_str(buf2, sizeof buf2,
404                                                &startp, endp)) < 0) {
405                                        if (cp != (sp2 + INT16SZ))
406                                                break;
407                                        return (-1);
408                                }
409                                if (n > 255)
410                                        return (-1);
411                                ShrinkBuffer(n+1);
412                                *cp++ = n;
413                                memcpy(cp, buf2, n);
414                                cp += n;
415                        }
416                        break;
417                case T_X25:
418                        /* RFC1183 */
419                        if ((n = getstr_str(buf2, sizeof buf2, &startp,
420                                         endp)) < 0)
421                                return (-1);
422                        if (n > 255)
423                                return (-1);
424                        ShrinkBuffer(n+1);
425                        *cp++ = n;
426                        memcpy(cp, buf2, n);
427                        cp += n;
428                        break;
429                case T_ISDN:
430                        /* RFC1183 */
431                        if ((n = getstr_str(buf2, sizeof buf2, &startp,
432                                         endp)) < 0)
433                                return (-1);
434                        if ((n > 255) || (n == 0))
435                                return (-1);
436                        ShrinkBuffer(n+1);
437                        *cp++ = n;
438                        memcpy(cp, buf2, n);
439                        cp += n;
440                        if ((n = getstr_str(buf2, sizeof buf2, &startp,
441                                         endp)) < 0)
442                                n = 0;
443                        if (n > 255)
444                                return (-1);
445                        ShrinkBuffer(n+1);
446                        *cp++ = n;
447                        memcpy(cp, buf2, n);
448                        cp += n;
449                        break;
450                case T_NSAP:
451                        if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) {
452                                ShrinkBuffer(n);
453                                memcpy(cp, buf2, n);
454                                cp += n;
455                        } else {
456                                return (-1);
457                        }
458                        break;
459                case T_LOC:
460                        if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) {
461                                ShrinkBuffer(n);
462                                memcpy(cp, buf2, n);
463                                cp += n;
464                        } else
465                                return (-1);
466                        break;
467                case ns_t_sig:
468#ifdef _LIBC
469                        return (-1);
470#else
471                    {
472                        int sig_type, success, dateerror;
473                        u_int32_t exptime, timesigned;
474
475                        /* type */
476                        if ((n = getword_str(buf2, sizeof buf2,
477                                             &startp, endp)) < 0)
478                                return (-1);
479                        sig_type = sym_ston(__p_type_syms, buf2, &success);
480                        if (!success || sig_type == ns_t_any)
481                                return (-1);
482                        ShrinkBuffer(INT16SZ);
483                        PUTSHORT(sig_type, cp);
484                        /* alg */
485                        n = getnum_str(&startp, endp);
486                        if (n < 0)
487                                return (-1);
488                        ShrinkBuffer(1);
489                        *cp++ = n;
490                        /* labels */
491                        n = getnum_str(&startp, endp);
492                        if (n <= 0 || n > 255)
493                                return (-1);
494                        ShrinkBuffer(1);
495                        *cp++ = n;
496                        /* ottl  & expire */
497                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
498                                return (-1);
499                        exptime = ns_datetosecs(buf2, &dateerror);
500                        if (!dateerror) {
501                                ShrinkBuffer(INT32SZ);
502                                PUTLONG(rttl, cp);
503                        }
504                        else {
505                                char *ulendp;
506                                u_int32_t ottl;
507
508                                errno = 0;
509                                ottl = strtoul(buf2, &ulendp, 10);
510                                if (errno != 0 ||
511                                    (ulendp != NULL && *ulendp != '\0'))
512                                        return (-1);
513                                ShrinkBuffer(INT32SZ);
514                                PUTLONG(ottl, cp);
515                                if (!getword_str(buf2, sizeof buf2, &startp,
516                                                 endp))
517                                        return (-1);
518                                exptime = ns_datetosecs(buf2, &dateerror);
519                                if (dateerror)
520                                        return (-1);
521                        }
522                        /* expire */
523                        ShrinkBuffer(INT32SZ);
524                        PUTLONG(exptime, cp);
525                        /* timesigned */
526                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
527                                return (-1);
528                        timesigned = ns_datetosecs(buf2, &dateerror);
529                        if (!dateerror) {
530                                ShrinkBuffer(INT32SZ);
531                                PUTLONG(timesigned, cp);
532                        }
533                        else
534                                return (-1);
535                        /* footprint */
536                        n = getnum_str(&startp, endp);
537                        if (n < 0)
538                                return (-1);
539                        ShrinkBuffer(INT16SZ);
540                        PUTSHORT(n, cp);
541                        /* signer name */
542                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
543                                return (-1);
544                        n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
545                        if (n < 0)
546                                return (-1);
547                        cp += n;
548                        ShrinkBuffer(n);
549                        /* sig */
550                        if ((n = getword_str(buf2, sizeof buf2,
551                                             &startp, endp)) < 0)
552                                return (-1);
553                        siglen = b64_pton(buf2, buf3, sizeof(buf3));
554                        if (siglen < 0)
555                                return (-1);
556                        ShrinkBuffer(siglen);
557                        memcpy(cp, buf3, siglen);
558                        cp += siglen;
559                        break;
560                    }
561#endif
562                case ns_t_key:
563                        /* flags */
564                        n = gethexnum_str(&startp, endp);
565                        if (n < 0)
566                                return (-1);
567                        ShrinkBuffer(INT16SZ);
568                        PUTSHORT(n, cp);
569                        /* proto */
570                        n = getnum_str(&startp, endp);
571                        if (n < 0)
572                                return (-1);
573                        ShrinkBuffer(1);
574                        *cp++ = n;
575                        /* alg */
576                        n = getnum_str(&startp, endp);
577                        if (n < 0)
578                                return (-1);
579                        ShrinkBuffer(1);
580                        *cp++ = n;
581                        /* key */
582                        if ((n = getword_str(buf2, sizeof buf2,
583                                             &startp, endp)) < 0)
584                                return (-1);
585                        keylen = b64_pton(buf2, buf3, sizeof(buf3));
586                        if (keylen < 0)
587                                return (-1);
588                        ShrinkBuffer(keylen);
589                        memcpy(cp, buf3, keylen);
590                        cp += keylen;
591                        break;
592                case ns_t_nxt:
593                    {
594                        int success, nxt_type;
595                        u_char data[32];
596                        int maxtype;
597
598                        /* next name */
599                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
600                                return (-1);
601                        n = dn_comp(buf2, cp, buflen, NULL, NULL);
602                        if (n < 0)
603                                return (-1);
604                        cp += n;
605                        ShrinkBuffer(n);
606                        maxtype = 0;
607                        memset(data, 0, sizeof data);
608                        for (;;) {
609                                if (!getword_str(buf2, sizeof buf2, &startp,
610                                                 endp))
611                                        break;
612                                nxt_type = sym_ston(__p_type_syms, buf2,
613                                                    &success);
614                                if (!success || !ns_t_rr_p(nxt_type))
615                                        return (-1);
616                                NS_NXT_BIT_SET(nxt_type, data);
617                                if (nxt_type > maxtype)
618                                        maxtype = nxt_type;
619                        }
620                        n = maxtype/NS_NXT_BITS+1;
621                        ShrinkBuffer(n);
622                        memcpy(cp, data, n);
623                        cp += n;
624                        break;
625                    }
626                case ns_t_cert:
627                        /* type */
628                        n = getnum_str(&startp, endp);
629                        if (n < 0)
630                                return (-1);
631                        ShrinkBuffer(INT16SZ);
632                        PUTSHORT(n, cp);
633                        /* key tag */
634                        n = getnum_str(&startp, endp);
635                        if (n < 0)
636                                return (-1);
637                        ShrinkBuffer(INT16SZ);
638                        PUTSHORT(n, cp);
639                        /* alg */
640                        n = getnum_str(&startp, endp);
641                        if (n < 0)
642                                return (-1);
643                        ShrinkBuffer(1);
644                        *cp++ = n;
645                        /* cert */
646                        if ((n = getword_str(buf2, sizeof buf2,
647                                             &startp, endp)) < 0)
648                                return (-1);
649                        certlen = b64_pton(buf2, buf3, sizeof(buf3));
650                        if (certlen < 0)
651                                return (-1);
652                        ShrinkBuffer(certlen);
653                        memcpy(cp, buf3, certlen);
654                        cp += certlen;
655                        break;
656                case ns_t_aaaa:
657                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
658                                return (-1);
659                        if (inet_pton(AF_INET6, buf2, &in6a) <= 0)
660                                return (-1);
661                        ShrinkBuffer(NS_IN6ADDRSZ);
662                        memcpy(cp, &in6a, NS_IN6ADDRSZ);
663                        cp += NS_IN6ADDRSZ;
664                        break;
665                case ns_t_naptr:
666                        /* Order Preference Flags Service Replacement Regexp */
667                        /* Order */
668                        n = getnum_str(&startp, endp);
669                        if (n < 0 || n > 65535)
670                                return (-1);
671                        ShrinkBuffer(INT16SZ);
672                        PUTSHORT(n, cp);
673                        /* Preference */
674                        n = getnum_str(&startp, endp);
675                        if (n < 0 || n > 65535)
676                                return (-1);
677                        ShrinkBuffer(INT16SZ);
678                        PUTSHORT(n, cp);
679                        /* Flags */
680                        if ((n = getstr_str(buf2, sizeof buf2,
681                                        &startp, endp)) < 0) {
682                                return (-1);
683                        }
684                        if (n > 255)
685                                return (-1);
686                        ShrinkBuffer(n+1);
687                        *cp++ = n;
688                        memcpy(cp, buf2, n);
689                        cp += n;
690                        /* Service Classes */
691                        if ((n = getstr_str(buf2, sizeof buf2,
692                                        &startp, endp)) < 0) {
693                                return (-1);
694                        }
695                        if (n > 255)
696                                return (-1);
697                        ShrinkBuffer(n+1);
698                        *cp++ = n;
699                        memcpy(cp, buf2, n);
700                        cp += n;
701                        /* Pattern */
702                        if ((n = getstr_str(buf2, sizeof buf2,
703                                        &startp, endp)) < 0) {
704                                return (-1);
705                        }
706                        if (n > 255)
707                                return (-1);
708                        ShrinkBuffer(n+1);
709                        *cp++ = n;
710                        memcpy(cp, buf2, n);
711                        cp += n;
712                        /* Replacement */
713                        if (!getword_str(buf2, sizeof buf2, &startp, endp))
714                                return (-1);
715                        n = dn_comp(buf2, cp, buflen, NULL, NULL);
716                        if (n < 0)
717                                return (-1);
718                        cp += n;
719                        ShrinkBuffer(n);
720                        break;
721                default:
722                        return (-1);
723                } /*switch*/
724                n = (u_int16_t)((cp - sp2) - INT16SZ);
725                PUTSHORT(n, sp2);
726        } /*for*/
727               
728        hp->qdcount = htons(counts[0]);
729        hp->ancount = htons(counts[1]);
730        hp->nscount = htons(counts[2]);
731        hp->arcount = htons(counts[3]);
732        return (cp - buf);
733}
734
735/*%
736 * Get a whitespace delimited word from a string (not file)
737 * into buf. modify the start pointer to point after the
738 * word in the string.
739 */
740static int
741getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
742        char *cp;
743        int c;
744 
745        for (cp = buf; *startpp <= endp; ) {
746                c = **startpp;
747                if (isspace(c) || c == '\0') {
748                        if (cp != buf) /*%< trailing whitespace */
749                                break;
750                        else { /*%< leading whitespace */
751                                (*startpp)++;
752                                continue;
753                        }
754                }
755                (*startpp)++;
756                if (cp >= buf+size-1)
757                        break;
758                *cp++ = (u_char)c;
759        }
760        *cp = '\0';
761        return (cp != buf);
762}
763
764/*%
765 * get a white spae delimited string from memory.  Process quoted strings
766 * and \\DDD escapes.  Return length or -1 on error.  Returned string may
767 * contain nulls.
768 */
769static char digits[] = "0123456789";
770static int
771getstr_str(char *buf, int size, u_char **startpp, u_char *endp) {
772        char *cp;
773        int c, c1 = 0;
774        int inquote = 0;
775        int seen_quote = 0;
776        int escape = 0;
777        int dig = 0;
778 
779        for (cp = buf; *startpp <= endp; ) {
780                if ((c = **startpp) == '\0')
781                        break;
782                /* leading white space */
783                if ((cp == buf) && !seen_quote && isspace(c)) {
784                        (*startpp)++;
785                        continue;
786                }
787
788                switch (c) {
789                case '\\':
790                        if (!escape)  {
791                                escape = 1;
792                                dig = 0;
793                                c1 = 0;
794                                (*startpp)++;
795                                continue;
796                        }
797                        goto do_escape;
798                case '"':
799                        if (!escape) {
800                                inquote = !inquote;
801                                seen_quote = 1;
802                                (*startpp)++;
803                                continue;
804                        }
805                        /* fall through */
806                default:
807                do_escape:
808                        if (escape) {
809                                switch (c) {
810                                case '0':
811                                case '1':
812                                case '2':
813                                case '3':
814                                case '4':
815                                case '5':
816                                case '6':
817                                case '7':
818                                case '8':
819                                case '9':
820                                        c1 = c1 * 10 +
821                                                (strchr(digits, c) - digits);
822
823                                        if (++dig == 3) {
824                                                c = c1 &0xff;
825                                                break;
826                                        }
827                                        (*startpp)++;
828                                        continue;
829                                }
830                                escape = 0;
831                        } else if (!inquote && isspace(c))
832                                goto done;
833                        if (cp >= buf+size-1)
834                                goto done;
835                        *cp++ = (u_char)c;
836                        (*startpp)++;
837                }
838        }
839 done:
840        *cp = '\0';
841        return ((cp == buf)?  (seen_quote? 0: -1): (cp - buf));
842}
843
844/*%
845 * Get a whitespace delimited base 16 number from a string (not file) into buf
846 * update the start pointer to point after the number in the string.
847 */
848static int
849gethexnum_str(u_char **startpp, u_char *endp) {
850        int c, n;
851        int seendigit = 0;
852        int m = 0;
853
854        if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0)
855                return getnum_str(startpp, endp);
856        (*startpp)+=2;
857        for (n = 0; *startpp <= endp; ) {
858                c = **startpp;
859                if (isspace(c) || c == '\0') {
860                        if (seendigit) /*%< trailing whitespace */
861                                break;
862                        else { /*%< leading whitespace */
863                                (*startpp)++;
864                                continue;
865                        }
866                }
867                if (c == ';') {
868                        while ((*startpp <= endp) &&
869                               ((c = **startpp) != '\n'))
870                                        (*startpp)++;
871                        if (seendigit)
872                                break;
873                        continue;
874                }
875                if (!isxdigit(c)) {
876                        if (c == ')' && seendigit) {
877                                (*startpp)--;
878                                break;
879                        }
880                        return (-1);
881                }       
882                (*startpp)++;
883                if (isdigit(c))
884                        n = n * 16 + (c - '0');
885                else
886                        n = n * 16 + (tolower(c) - 'a' + 10);
887                seendigit = 1;
888        }
889        return (n + m);
890}
891
892/*%
893 * Get a whitespace delimited base 10 number from a string (not file) into buf
894 * update the start pointer to point after the number in the string.
895 */
896static int
897getnum_str(u_char **startpp, u_char *endp) {
898        int c, n;
899        int seendigit = 0;
900        int m = 0;
901
902        for (n = 0; *startpp <= endp; ) {
903                c = **startpp;
904                if (isspace(c) || c == '\0') {
905                        if (seendigit) /*%< trailing whitespace */
906                                break;
907                        else { /*%< leading whitespace */
908                                (*startpp)++;
909                                continue;
910                        }
911                }
912                if (c == ';') {
913                        while ((*startpp <= endp) &&
914                               ((c = **startpp) != '\n'))
915                                        (*startpp)++;
916                        if (seendigit)
917                                break;
918                        continue;
919                }
920                if (!isdigit(c)) {
921                        if (c == ')' && seendigit) {
922                                (*startpp)--;
923                                break;
924                        }
925                        return (-1);
926                }       
927                (*startpp)++;
928                n = n * 10 + (c - '0');
929                seendigit = 1;
930        }
931        return (n + m);
932}
933
934/*%
935 * Allocate a resource record buffer & save rr info.
936 */
937ns_updrec *
938res_mkupdrec(int section, const char *dname,
939             u_int class, u_int type, u_long ttl) {
940        ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec));
941
942        if (!rrecp || !(rrecp->r_dname = strdup(dname))) {
943                if (rrecp)
944                        free((char *)rrecp);
945                return (NULL);
946        }
947        INIT_LINK(rrecp, r_link);
948        INIT_LINK(rrecp, r_glink);
949        rrecp->r_class = (ns_class)class;
950        rrecp->r_type = (ns_type)type;
951        rrecp->r_ttl = ttl;
952        rrecp->r_section = (ns_sect)section;
953        return (rrecp);
954}
955
956/*%
957 * Free a resource record buffer created by res_mkupdrec.
958 */
959void
960res_freeupdrec(ns_updrec *rrecp) {
961        /* Note: freeing r_dp is the caller's responsibility. */
962        if (rrecp->r_dname != NULL)
963                free(rrecp->r_dname);
964        free(rrecp);
965}
966
967struct valuelist {
968        struct valuelist *      next;
969        struct valuelist *      prev;
970        char *                  name;
971        char *                  proto;
972        int                     port;
973};
974static struct valuelist *servicelist, *protolist;
975
976static void
977res_buildservicelist() {
978        struct servent *sp;
979        struct valuelist *slp;
980
981#ifdef MAYBE_HESIOD
982        setservent(0);
983#else
984        setservent(1);
985#endif
986        while ((sp = getservent()) != NULL) {
987                slp = (struct valuelist *)malloc(sizeof(struct valuelist));
988                if (!slp)
989                        break;
990                slp->name = strdup(sp->s_name);
991                slp->proto = strdup(sp->s_proto);
992                if ((slp->name == NULL) || (slp->proto == NULL)) {
993                        if (slp->name) free(slp->name);
994                        if (slp->proto) free(slp->proto);
995                        free(slp);
996                        break;
997                }
998                slp->port = ntohs((u_int16_t)sp->s_port);  /*%< host byt order */
999                slp->next = servicelist;
1000                slp->prev = NULL;
1001                if (servicelist)
1002                        servicelist->prev = slp;
1003                servicelist = slp;
1004        }
1005        endservent();
1006}
1007
1008#ifndef _LIBC
1009void
1010res_destroyservicelist() {
1011        struct valuelist *slp, *slp_next;
1012
1013        for (slp = servicelist; slp != NULL; slp = slp_next) {
1014                slp_next = slp->next;
1015                free(slp->name);
1016                free(slp->proto);
1017                free(slp);
1018        }
1019        servicelist = (struct valuelist *)0;
1020}
1021#endif
1022
1023#ifdef _LIBC
1024static
1025#endif
1026void
1027res_buildprotolist(void) {
1028        struct protoent *pp;
1029        struct valuelist *slp;
1030
1031#ifdef MAYBE_HESIOD
1032        setprotoent(0);
1033#else
1034        setprotoent(1);
1035#endif
1036        while ((pp = getprotoent()) != NULL) {
1037                slp = (struct valuelist *)malloc(sizeof(struct valuelist));
1038                if (!slp)
1039                        break;
1040                slp->name = strdup(pp->p_name);
1041                if (slp->name == NULL) {
1042                        free(slp);
1043                        break;
1044                }
1045                slp->port = pp->p_proto;        /*%< host byte order */
1046                slp->next = protolist;
1047                slp->prev = NULL;
1048                if (protolist)
1049                        protolist->prev = slp;
1050                protolist = slp;
1051        }
1052        endprotoent();
1053}
1054
1055#ifndef _LIBC
1056void
1057res_destroyprotolist(void) {
1058        struct valuelist *plp, *plp_next;
1059
1060        for (plp = protolist; plp != NULL; plp = plp_next) {
1061                plp_next = plp->next;
1062                free(plp->name);
1063                free(plp);
1064        }
1065        protolist = (struct valuelist *)0;
1066}
1067#endif
1068
1069static int
1070findservice(const char *s, struct valuelist **list) {
1071        struct valuelist *lp = *list;
1072        int n;
1073
1074        for (; lp != NULL; lp = lp->next)
1075                if (strcasecmp(lp->name, s) == 0) {
1076                        if (lp != *list) {
1077                                lp->prev->next = lp->next;
1078                                if (lp->next)
1079                                        lp->next->prev = lp->prev;
1080                                (*list)->prev = lp;
1081                                lp->next = *list;
1082                                *list = lp;
1083                        }
1084                        return (lp->port);      /*%< host byte order */
1085                }
1086        if (sscanf(s, "%d", &n) != 1 || n <= 0)
1087                n = -1;
1088        return (n);
1089}
1090
1091/*%
1092 * Convert service name or (ascii) number to int.
1093 */
1094#ifdef _LIBC
1095static
1096#endif
1097int
1098res_servicenumber(const char *p) {
1099        if (servicelist == (struct valuelist *)0)
1100                res_buildservicelist();
1101        return (findservice(p, &servicelist));
1102}
1103
1104/*%
1105 * Convert protocol name or (ascii) number to int.
1106 */
1107#ifdef _LIBC
1108static
1109#endif
1110int
1111res_protocolnumber(const char *p) {
1112        if (protolist == (struct valuelist *)0)
1113                res_buildprotolist();
1114        return (findservice(p, &protolist));
1115}
1116
1117#ifndef _LIBC
1118static struct servent *
1119cgetservbyport(u_int16_t port, const char *proto) {     /*%< Host byte order. */
1120        struct valuelist **list = &servicelist;
1121        struct valuelist *lp = *list;
1122        static struct servent serv;
1123
1124        port = ntohs(port);
1125        for (; lp != NULL; lp = lp->next) {
1126                if (port != (u_int16_t)lp->port)        /*%< Host byte order. */
1127                        continue;
1128                if (strcasecmp(lp->proto, proto) == 0) {
1129                        if (lp != *list) {
1130                                lp->prev->next = lp->next;
1131                                if (lp->next)
1132                                        lp->next->prev = lp->prev;
1133                                (*list)->prev = lp;
1134                                lp->next = *list;
1135                                *list = lp;
1136                        }
1137                        serv.s_name = lp->name;
1138                        serv.s_port = htons((u_int16_t)lp->port);
1139                        serv.s_proto = lp->proto;
1140                        return (&serv);
1141                }
1142        }
1143        return (0);
1144}
1145
1146static struct protoent *
1147cgetprotobynumber(int proto) {                          /*%< Host byte order. */
1148        struct valuelist **list = &protolist;
1149        struct valuelist *lp = *list;
1150        static struct protoent prot;
1151
1152        for (; lp != NULL; lp = lp->next)
1153                if (lp->port == proto) {                /*%< Host byte order. */
1154                        if (lp != *list) {
1155                                lp->prev->next = lp->next;
1156                                if (lp->next)
1157                                        lp->next->prev = lp->prev;
1158                                (*list)->prev = lp;
1159                                lp->next = *list;
1160                                *list = lp;
1161                        }
1162                        prot.p_name = lp->name;
1163                        prot.p_proto = lp->port;        /*%< Host byte order. */
1164                        return (&prot);
1165                }
1166        return (0);
1167}
1168
1169const char *
1170res_protocolname(int num) {
1171        static char number[8];
1172        struct protoent *pp;
1173
1174        if (protolist == (struct valuelist *)0)
1175                res_buildprotolist();
1176        pp = cgetprotobynumber(num);
1177        if (pp == 0)  {
1178                (void) sprintf(number, "%d", num);
1179                return (number);
1180        }
1181        return (pp->p_name);
1182}
1183
1184const char *
1185res_servicename(u_int16_t port, const char *proto) {    /*%< Host byte order. */
1186        static char number[8];
1187        struct servent *ss;
1188
1189        if (servicelist == (struct valuelist *)0)
1190                res_buildservicelist();
1191        ss = cgetservbyport(htons(port), proto);
1192        if (ss == 0)  {
1193                (void) sprintf(number, "%d", port);
1194                return (number);
1195        }
1196        return (ss->s_name);
1197}
1198#endif
Note: See TracBrowser for help on using the repository browser.