reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ares_mkquery.c
Go to the documentation of this file.
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose. It is provided "as is"
13 * without express or implied warranty.
14 */
15
16
17#include <sys/types.h>
18#ifndef WIN32
19#include <netinet/in.h>
20#ifndef __CYGWIN__
21# include "ares_nameser.h"
22#endif
23#endif
24#include <stdlib.h>
25#include <string.h>
26#include "ares.h"
27#include "ares_dns.h"
28
29/* Header format, from RFC 1035:
30 * 1 1 1 1 1 1
31 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
32 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
33 * | ID |
34 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
35 * |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
36 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
37 * | QDCOUNT |
38 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
39 * | ANCOUNT |
40 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
41 * | NSCOUNT |
42 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
43 * | ARCOUNT |
44 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
45 *
46 * AA, TC, RA, and RCODE are only set in responses. Brief description
47 * of the remaining fields:
48 * ID Identifier to match responses with queries
49 * QR Query (0) or response (1)
50 * Opcode For our purposes, always QUERY
51 * RD Recursion desired
52 * Z Reserved (zero)
53 * QDCOUNT Number of queries
54 * ANCOUNT Number of answers
55 * NSCOUNT Number of name server records
56 * ARCOUNT Number of additional records
57 *
58 * Question format, from RFC 1035:
59 * 1 1 1 1 1 1
60 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
61 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
62 * | |
63 * / QNAME /
64 * / /
65 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
66 * | QTYPE |
67 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
68 * | QCLASS |
69 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
70 *
71 * The query name is encoded as a series of labels, each represented
72 * as a one-byte length (maximum 63) followed by the text of the
73 * label. The list is terminated by a label of length zero (which can
74 * be thought of as the root domain).
75 */
76
77int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id,
78 int rd, unsigned char **buf, int *buflen)
79{
80 size_t len;
81 unsigned char *q;
82 const char *p;
83
84 /* Allocate a memory area for the maximum size this packet might need. +2
85 * is for the length byte and zero termination if no dots or ecscaping is
86 * used.
87 */
88 *buflen = (int)(strlen(name) + 2 + HFIXEDSZ + QFIXEDSZ);
89 *buf = malloc(*buflen);
90 if (!*buf)
91 return ARES_ENOMEM;
92
93 /* Set up the header. */
94 q = *buf;
95 memset(q, 0, HFIXEDSZ);
98 DNS_HEADER_SET_RD(q, (rd) ? 1 : 0);
100
101 /* A name of "." is a screw case for the loop below, so adjust it. */
102 if (strcmp(name, ".") == 0)
103 name++;
104
105 /* Start writing out the name after the header. */
106 q += HFIXEDSZ;
107 while (*name)
108 {
109 if (*name == '.')
110 return ARES_EBADNAME;
111
112 /* Count the number of bytes in this label. */
113 len = 0;
114 for (p = name; *p && *p != '.'; p++)
115 {
116 if (*p == '\\' && *(p + 1) != 0)
117 p++;
118 len++;
119 }
120 if (len > MAXLABEL)
121 return ARES_EBADNAME;
122
123 /* Encode the length and copy the data. */
124 *q++ = (unsigned char)len;
125 for (p = name; *p && *p != '.'; p++)
126 {
127 if (*p == '\\' && *(p + 1) != 0)
128 p++;
129 *q++ = *p;
130 }
131
132 /* Go to the next label and repeat, unless we hit the end. */
133 if (!*p)
134 break;
135 name = p + 1;
136 }
137
138 /* Add the zero-length label at the end. */
139 *q++ = 0;
140
141 /* Finish off the question with the type and class. */
143 DNS_QUESTION_SET_CLASS(q, dnsclass);
144
145 q += QFIXEDSZ;
146
147 len = (q - *buf);
148
149 /* Reject names that are longer than the maximum of 255 bytes that's
150 * specified in RFC 1035 ("To simplify implementations, the total length of
151 * a domain name (i.e., label octets and label length octets) is restricted
152 * to 255 octets or less."). */
153 if (len > (MAXCDNAME + HFIXEDSZ + QFIXEDSZ)) {
154 return ARES_EBADNAME;
155 }
156
157 /* we know this fits in an int at this point */
158 *buflen = (int)len;
159
160 return ARES_SUCCESS;
161}
#define ARES_SUCCESS
Definition ares.h:79
#define ARES_ENOMEM
Definition ares.h:98
#define ARES_EBADNAME
Definition ares.h:91
#define DNS_HEADER_SET_OPCODE(h, v)
Definition ares_dns.h:47
#define DNS_HEADER_SET_QDCOUNT(h, v)
Definition ares_dns.h:54
#define DNS_QUESTION_SET_TYPE(q, v)
Definition ares_dns.h:64
#define DNS_HEADER_SET_RD(h, v)
Definition ares_dns.h:50
#define DNS_HEADER_SET_QID(h, v)
Definition ares_dns.h:45
#define DNS_QUESTION_SET_CLASS(q, v)
Definition ares_dns.h:65
int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id, int rd, unsigned char **buf, int *buflen)
#define QFIXEDSZ
#define MAXCDNAME
#define MAXLABEL
#define HFIXEDSZ
#define QUERY
void list()
Definition userAdmin.cxx:66