2 * Copyright (c) 1985 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution
11 * and in all advertising materials mentioning features or use of this
12 * software. Neither the name of the University nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 #if defined(LIBC_SCCS) && !defined(lint)
21 static char sccsid
[] = "@(#)res_mkquery.c 6.12 (Berkeley) 6/1/90";
22 #endif /* LIBC_SCCS and not lint */
25 #include <sys/types.h>
31 #include <net/gen/in.h>
32 #include <net/gen/nameser.h>
33 #include <net/gen/resolv.h>
35 #define bzero(b,l) memset(b,0,l)
36 #define bcopy(s,d,l) memcpy(d,s,l)
38 #define putshort __putshort
39 #define putlong __putlong
42 #include <sys/types.h>
43 #include <netinet/in.h>
44 #include <arpa/nameser.h>
55 * Form all types of queries.
56 * Returns the size of the result or -1.
58 res_mkquery(op
, dname
, class, type
, data
, datalen
, newrr
, buf
, buflen
)
59 int op
; /* opcode of query */
60 _CONST
char *dname
; /* domain name */
61 int class, type
; /* class and type of query */
62 _CONST
char *data
; /* resource record data */
63 int datalen
; /* length of data */
64 _CONST
struct rrec
*newrr
; /* new rr for modify or append */
65 char *buf
; /* buffer to put query */
66 int buflen
; /* size of buffer */
68 register dns_hdr_t
*hp
;
71 char *dnptrs
[10], **dpp
, **lastdnptr
;
74 if (_res
.options
& RES_DEBUG
)
75 printf("res_mkquery(%d, %s, %d, %d)\n", op
, dname
, class, type
);
78 * Initialize header fields.
80 if ((buf
== NULL
) || (buflen
< sizeof(dns_hdr_t
)))
82 bzero(buf
, sizeof(dns_hdr_t
));
83 hp
= (dns_hdr_t
*) buf
;
84 hp
->dh_id
= htons(++_res
.id
);
87 hp
->dh_flag1
|= (op
<< 3) & DHF_OPCODE
;
88 hp
->dh_flag2
|= ((_res
.options
& RES_PRIMARY
) != 0 ? 1 : 0) << 6;
89 hp
->dh_flag1
|= (_res
.options
& RES_RECURSE
) != 0 ? 1 : 0;
90 hp
->dh_flag2
|= NOERROR
& DHF_RCODE
;
91 cp
= buf
+ sizeof(dns_hdr_t
);
92 buflen
-= sizeof(dns_hdr_t
);
96 lastdnptr
= dnptrs
+ sizeof(dnptrs
)/sizeof(dnptrs
[0]);
98 * perform opcode specific processing
102 if ((buflen
-= QFIXEDSZ
) < 0)
104 if ((n
= dn_comp((u8_t
*)dname
, (u8_t
*)cp
, buflen
,
105 (u8_t
**)dnptrs
, (u8_t
**)lastdnptr
)) < 0)
109 putshort(type
, (u8_t
*)cp
);
110 cp
+= sizeof(u_short
);
111 putshort(class, (u8_t
*)cp
);
112 cp
+= sizeof(u_short
);
113 hp
->dh_qdcount
= HTONS(1);
114 if (op
== QUERY
|| data
== NULL
)
117 * Make an additional record for completion domain.
120 if ((n
= dn_comp((u8_t
*)data
, (u8_t
*)cp
, buflen
,
121 (u8_t
**)dnptrs
, (u8_t
**)lastdnptr
)) < 0)
125 putshort(T_NULL
, (u8_t
*)cp
);
126 cp
+= sizeof(u_short
);
127 putshort(class, (u8_t
*)cp
);
128 cp
+= sizeof(u_short
);
129 putlong(0, (u8_t
*)cp
);
130 cp
+= sizeof(u_long
);
131 putshort(0, (u8_t
*)cp
);
132 cp
+= sizeof(u_short
);
133 hp
->dh_arcount
= HTONS(1);
138 * Initialize answer section
140 if (buflen
< 1 + RRFIXEDSZ
+ datalen
)
142 *cp
++ = '\0'; /* no domain name */
143 putshort(type
, (u8_t
*)cp
);
144 cp
+= sizeof(u_short
);
145 putshort(class, (u8_t
*)cp
);
146 cp
+= sizeof(u_short
);
147 putlong(0, (u8_t
*)cp
);
148 cp
+= sizeof(u_long
);
149 putshort(datalen
, (u8_t
*)cp
);
150 cp
+= sizeof(u_short
);
152 bcopy(data
, cp
, datalen
);
155 hp
->dh_ancount
= HTONS(1);
160 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
161 * (Record to be modified is followed by its replacement in msg.)
168 * The res code for UPDATED and UPDATEDA is the same; user
169 * calls them differently: specifies data for UPDATED; server
170 * ignores data if specified for UPDATEDA.
173 buflen
-= RRFIXEDSZ
+ datalen
;
174 if ((n
= dn_comp(dname
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
178 cp
+= sizeof(u_short
);
180 cp
+= sizeof(u_short
);
182 cp
+= sizeof(u_long
);
183 putshort(datalen
, cp
);
184 cp
+= sizeof(u_short
);
186 bcopy(data
, cp
, datalen
);
189 if ( (op
== UPDATED
) || (op
== UPDATEDA
) ) {
190 hp
->ancount
= HTONS(0);
193 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
195 case UPDATEA
: /* Add new resource record */
196 buflen
-= RRFIXEDSZ
+ datalen
;
197 if ((n
= dn_comp(dname
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
200 putshort(newrr
->r_type
, cp
);
201 cp
+= sizeof(u_short
);
202 putshort(newrr
->r_class
, cp
);
203 cp
+= sizeof(u_short
);
205 cp
+= sizeof(u_long
);
206 putshort(newrr
->r_size
, cp
);
207 cp
+= sizeof(u_short
);
209 bcopy(newrr
->r_data
, cp
, newrr
->r_size
);
212 hp
->ancount
= HTONS(0);
215 #endif /* ALLOW_UPDATES */