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

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f41a394 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

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