/
HITPDNSLogType1FieldSetMapper.kt
102 lines (95 loc) · 3.62 KB
/
HITPDNSLogType1FieldSetMapper.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package com.hitnslab.dnssecurity.deeparcher.pdnsdataloader.parsing
import com.hitnslab.dnssecurity.deeparcher.model.PDnsData
import com.hitnslab.dnssecurity.deeparcher.pdnsdataloader.error.PDNSInvalidFormatException
import mu.KotlinLogging
import org.springframework.batch.item.file.transform.FieldSet
import java.time.format.DateTimeFormatter
/**
*
* Example:
* 0 2019-11-02T00:00:00.010625+08:00
* 1 10.235.1.2
* 2 01-Nov-2019
* 3 23:56:39.157
* 4 client
* 5 10.240.60.123
* 6 49470:
* 7 view
* 8 WH_Student:
* 9 tile-service.weather.microsoft.com
* 10 IN
* 11 A
* 12 NOERROR
* 13 +
* 14 NS
* 15 NE
* 16 NT
* 17 ND
* 18 NC
* 19 H
* 20 26
* 21 Response:
* 22 tile-service.weather.microsoft.com 499 IN CNAME wildcard.weather.microsoft.com.edgekey.net.;wildcard.weather.microsoft.com.edgekey.net 780 IN CNAME e15275.g.akamaiedge.net.;e15275.g.akamaiedge.net 60 IN A 184.85.125.248;
*/
class HITPDNSLogType1FieldSetMapper : PDNSLogFieldSetMapper {
private val dataStringBuilder = StringBuffer(3)
private val dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm:ss.nnn")
private val logger = KotlinLogging.logger {}
override fun mapFieldSet(fieldSet: FieldSet): PDnsData.Builder {
val queryTime: String
try {
synchronized(this) {
dataStringBuilder.setLength(0)
dataStringBuilder.append(fieldSet.readString(2))
.append(" ")
.append(fieldSet.readString(3))
queryTime = dataStringBuilder.toString()
}
} catch (e: Exception) {
throw PDNSInvalidFormatException("PDNS parse failed: Invalid queryTime in fieldSet <$fieldSet>, exception <$e>", e)
}
val values = fieldSet.values
val builder = PDnsData.Builder()
.queryTime(queryTime, dateTimeFormatter)
.domain(fieldSet.readString(9))
.queryType(fieldSet.readString(11))
.replyCode(fieldSet.readString(12))
val size = values.size
if (size <= 14) {
throw PDNSInvalidFormatException("PDNS parse failed: Insufficient number of fields in <$fieldSet>")
}
builder.clientIp(fieldSet.readString(5))
var hasResponseBody = false
var bodyBaseIdx = -1
for (i in 13 until size) {
if (values[i].trim() == "Response:") {
hasResponseBody = true
bodyBaseIdx = i + 1
break
}
}
if (hasResponseBody) {
var entryStart = bodyBaseIdx
do {
val entryEnd = entryStart + 4
if (entryEnd >= size) {
// logger.warn { "Malformed DNS reply entry: <${values.slice(entryStart until size)}>" }
break
}
val replyType = values[entryStart + 3].trim()
val conjunction = values[entryStart + 4]
if (';' !in conjunction) {
logger.warn { "Malformed DNS reply entry conjunction data: <$conjunction>" }
break
}
val replyData: String = conjunction.split(";")[0].trimEnd('.')
when (replyType) {
"CNAME" -> builder.addCName(replyData)
"A", "AAAA" -> builder.addIp(replyData)
}
entryStart = entryEnd
} while (entryStart < size - 1)
}
return builder
}
}