Add the parameter 'over_tcp'.
Move the shift by 2 bytes from the TCP printer to the DNS printer.
Move adding a prepended space from the TCP printer to the DNS printer.
Add a length check.
Add some comments about 'over_tcp' and 'is_mdns' call values.
extern void nfsreply_noaddr_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern void nfsreq_noaddr_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern const u_char *fqdn_print(netdissect_options *, const u_char *, const u_char *);
-extern void domain_print(netdissect_options *, const u_char *, u_int, int);
+extern void domain_print(netdissect_options *, const u_char *, u_int, int, int);
extern void nsh_print(netdissect_options *, const u_char *, u_int);
extern void ntp_print(netdissect_options *, const u_char *, u_int);
extern void oam_print(netdissect_options *, const u_char *, u_int, u_int);
void
domain_print(netdissect_options *ndo,
- const u_char *bp, u_int length, int is_mdns)
+ const u_char *bp, u_int length, int over_tcp, int is_mdns)
{
const dns_header_t *np;
uint16_t flags, rcode, rdlen, type;
uint16_t b2;
ndo->ndo_protocol = "domain";
+
+ if (over_tcp) {
+ /*
+ * The message is prefixed with a two byte length field
+ * which gives the message length, excluding the two byte
+ * length field. (RFC 1035 - 4.2.2. TCP usage)
+ */
+ if (length < 2) {
+ ND_PRINT(" [DNS over TCP: length %u < 2]", length);
+ nd_print_invalid(ndo);
+ return;
+ } else {
+ length -= 2; /* excluding the two byte length field */
+ if (GET_BE_U_2(bp) != length) {
+ ND_PRINT(" [prefix length(%u) != length(%u)]",
+ GET_BE_U_2(bp), length);
+ nd_print_invalid(ndo);
+ return;
+ } else {
+ bp += 2;
+ /* in over TCP case, we need to prepend a space
+ * (not needed in over UDP case)
+ */
+ ND_PRINT(" ");
+ }
+ }
+ }
+
np = (const dns_header_t *)bp;
if(length < sizeof(*np)) {
resp_print(ndo, bp, length);
break;
case PT_DOMAIN:
- ND_PRINT(" ");
- domain_print(ndo, bp + 2, length - 2, 0);
+ /* over_tcp: TRUE, is_mdns: FALSE */
+ domain_print(ndo, bp, length, TRUE, FALSE);
break;
}
return;
} else if (IS_SRC_OR_DST_PORT(RTSP_PORT) || IS_SRC_OR_DST_PORT(RTSP_PORT_ALT)) {
ND_PRINT(": ");
rtsp_print(ndo, bp, length);
- } else if (length > 2 &&
- (IS_SRC_OR_DST_PORT(NAMESERVER_PORT))) {
- /* domain_print() assumes it does not have to prepend a space before its
- * own output to separate it from the output of the calling function. This
- * works well with udp_print(), but requires a small prop here.
- */
- ND_PRINT(" ");
-
- /*
- * TCP DNS query has 2byte length at the head.
- * XXX packet could be unaligned, it can go strange
- */
- domain_print(ndo, bp + 2, length - 2, 0);
+ } else if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT)) {
+ /* over_tcp: TRUE, is_mdns: FALSE */
+ domain_print(ndo, bp, length, TRUE, FALSE);
} else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) {
msdp_print(ndo, bp, length);
} else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) {
break;
case PT_DOMAIN:
udpipaddr_print(ndo, ip, sport, dport);
- domain_print(ndo, cp, length, 0);
+ /* over_tcp: FALSE, is_mdns: FALSE */
+ domain_print(ndo, cp, length, FALSE, FALSE);
break;
}
return;
if (!ndo->ndo_qflag) {
if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT))
- domain_print(ndo, cp, length, 0);
+ /* over_tcp: FALSE, is_mdns: FALSE */
+ domain_print(ndo, cp, length, FALSE, FALSE);
else if (IS_SRC_OR_DST_PORT(MULTICASTDNS_PORT))
- domain_print(ndo, cp, length, 1);
+ /* over_tcp: FALSE, is_mdns: TRUE */
+ domain_print(ndo, cp, length, FALSE, TRUE);
else if (IS_SRC_OR_DST_PORT(TIMED_PORT))
timed_print(ndo, (const u_char *)cp);
else if (IS_SRC_OR_DST_PORT(TFTP_PORT))