all repos

scratch @ bc17d480554cde516be3fa2adc55455aadfebc1a

⭐ me doing recreational ~~drugs~~ programming
6 files changed, 141 insertions(+), 12 deletions(-)
dns: ch2
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-03-21 13:25:41 +0200
Authored at: 2026-03-20 15:54:36 +0200
Change ID: umpoxznltvsykxqvlnkpvokwmrrxwyql
Parent: 77539db
M dns-server/header.go
···
        6
        6
         	"fmt"

      
        7
        7
         )

      
        8
        8
         

      
        9
        
        -type ResultCode uint

      
        
        9
        +type ResultCode = uint8

      
        10
        10
         

      
        11
        11
         const (

      
        12
        12
         	NOERROR ResultCode = iota

      ···
        65
        65
         	return h, nil

      
        66
        66
         }

      
        67
        67
         

      
        
        68
        +func (h *Header) Write(b *bytes.Buffer) error {

      
        
        69
        +	_ = binary.Write(b, binary.BigEndian, h.ID)

      
        
        70
        +

      
        
        71
        +	_ = b.WriteByte((b2u8(h.RecursionDesired)) |

      
        
        72
        +		(b2u8(h.TruncatedMessage) << 1) |

      
        
        73
        +		(b2u8(h.AuthoritativeAnswer) << 2) |

      
        
        74
        +		(h.OPCode << 3) |

      
        
        75
        +		(b2u8(h.Response) << 7))

      
        
        76
        +

      
        
        77
        +	_ = b.WriteByte(h.Rescode |

      
        
        78
        +		(b2u8(h.CheckingDisabled) << 4) |

      
        
        79
        +		(b2u8(h.AuthedData) << 5) |

      
        
        80
        +		(b2u8(h.Z) << 6) |

      
        
        81
        +		(b2u8(h.RecursionAvailable) << 7))

      
        
        82
        +

      
        
        83
        +	_ = binary.Write(b, binary.BigEndian, h.Questions)

      
        
        84
        +	_ = binary.Write(b, binary.BigEndian, h.Answers)

      
        
        85
        +	_ = binary.Write(b, binary.BigEndian, h.AuthoritativeEntries)

      
        
        86
        +	_ = binary.Write(b, binary.BigEndian, h.ResourceEntries)

      
        
        87
        +	return nil

      
        
        88
        +}

      
        
        89
        +

      
        68
        90
         func (h *Header) unpackFlags(flags uint16) {

      
        69
        91
         	h.RecursionDesired = flags&(1<<8) != 0

      
        70
        92
         	h.TruncatedMessage = flags&(1<<9) != 0

      ···
        108
        130
         	}

      
        109
        131
         	return flags

      
        110
        132
         }

      
        
        133
        +

      
        
        134
        +func b2u8(b bool) uint8 {

      
        
        135
        +	if b {

      
        
        136
        +		return 1

      
        
        137
        +	}

      
        
        138
        +	return 0

      
        
        139
        +}

      
M dns-server/main.go
···
        1
        1
         package main

      
        2
        2
         

      
        3
        3
         import (

      
        
        4
        +	"bytes"

      
        4
        5
         	_ "embed"

      
        5
        6
         	"fmt"

      
        
        7
        +	"net"

      
        6
        8
         )

      
        7
        9
         

      
        8
        
        -//go:embed response_packet.txt

      
        9
        
        -var respPack []byte

      
        
        10
        +func main() {

      
        
        11
        +	qname := "google.com"

      
        
        12
        +	server := "8.8.8.8:53"

      
        
        13
        +

      
        
        14
        +	conn, _ := net.Dial("udp", server)

      
        
        15
        +	defer conn.Close()

      
        
        16
        +

      
        
        17
        +	p := Packet{}

      
        
        18
        +	p.Header.ID = 6666

      
        
        19
        +	p.Header.RecursionDesired = true

      
        
        20
        +	p.Questions = append(p.Questions, Question{

      
        
        21
        +		Name:  qname,

      
        
        22
        +		Type:  1, // A

      
        
        23
        +		Class: 1, // IN

      
        
        24
        +	})

      
        
        25
        +

      
        
        26
        +	buf := &bytes.Buffer{}

      
        
        27
        +	if err := p.Write(buf); err != nil {

      
        
        28
        +		fmt.Printf("failed to write packet: %v", err)

      
        
        29
        +	}

      
        
        30
        +

      
        
        31
        +	if _, err := conn.Write(buf.Bytes()); err != nil {

      
        
        32
        +		fmt.Printf("failed to write to connection: %v", err)

      
        
        33
        +	}

      
        10
        34
         

      
        11
        
        -func main() {

      
        12
        
        -	p, err := ParsePacket(respPack)

      
        
        35
        +	res := make([]byte, 512)

      
        
        36
        +	n, err := conn.Read(res)

      
        13
        37
         	if err != nil {

      
        14
        
        -		panic(err)

      
        
        38
        +		fmt.Printf("failed to read from connection: %v", err)

      
        15
        39
         	}

      
        16
        40
         

      
        17
        
        -	fmt.Printf("%+v\n", p.Header)

      
        18
        
        -	for _, q := range p.Questions {

      
        
        41
        +	resPack, err := ParsePacket(res[:n])

      
        
        42
        +	if err != nil {

      
        
        43
        +		fmt.Printf("failed to parse packet: %v", err)

      
        
        44
        +	}

      
        
        45
        +

      
        
        46
        +	fmt.Printf("%+v\n", resPack.Header)

      
        
        47
        +	for _, q := range resPack.Questions {

      
        19
        48
         		fmt.Printf("%+v\n", q)

      
        20
        49
         	}

      
        21
        
        -	for _, r := range p.Answers {

      
        
        50
        +	for _, r := range resPack.Answers {

      
        22
        51
         		fmt.Printf("%+v\n", r)

      
        23
        52
         	}

      
        24
        
        -	for _, r := range p.Authorities {

      
        
        53
        +	for _, r := range resPack.Authorities {

      
        25
        54
         		fmt.Printf("%+v\n", r)

      
        26
        55
         	}

      
        27
        
        -	for _, r := range p.Resources {

      
        
        56
        +	for _, r := range resPack.Resources {

      
        28
        57
         		fmt.Printf("%+v\n", r)

      
        29
        58
         	}

      
        30
        59
         }

      
M dns-server/packet.go
···
        21
        21
         		return Packet{}, err

      
        22
        22
         	}

      
        23
        23
         

      
        24
        
        -	// TODO: don't do int(Questions) ????

      
        25
        24
         	for i := 0; i < int(p.Header.Questions); i++ {

      
        26
        25
         		q, err := ReadQuestion(r, packet)

      
        27
        26
         		if err != nil {

      ···
        56
        55
         

      
        57
        56
         	return p, nil

      
        58
        57
         }

      
        
        58
        +

      
        
        59
        +func (p *Packet) Write(b *bytes.Buffer) error {

      
        
        60
        +	p.Header.Questions = uint16(len(p.Questions))

      
        
        61
        +	p.Header.Answers = uint16(len(p.Answers))

      
        
        62
        +	p.Header.AuthoritativeEntries = uint16(len(p.Authorities))

      
        
        63
        +	p.Header.ResourceEntries = uint16(len(p.Resources))

      
        
        64
        +	_ = p.Header.Write(b)

      
        
        65
        +

      
        
        66
        +	for i := range p.Questions {

      
        
        67
        +		_ = p.Questions[i].Write(b)

      
        
        68
        +	}

      
        
        69
        +

      
        
        70
        +	for i := range p.Answers {

      
        
        71
        +		_, _ = p.Answers[i].Write(b)

      
        
        72
        +	}

      
        
        73
        +

      
        
        74
        +	for i := range p.Authorities {

      
        
        75
        +		_, _ = p.Authorities[i].Write(b)

      
        
        76
        +	}

      
        
        77
        +

      
        
        78
        +	for i := range p.Resources {

      
        
        79
        +		_, _ = p.Resources[i].Write(b)

      
        
        80
        +	}

      
        
        81
        +

      
        
        82
        +	return nil

      
        
        83
        +}

      
M dns-server/question.go
···
        27
        27
         		Class: qclass,

      
        28
        28
         	}, nil

      
        29
        29
         }

      
        
        30
        +

      
        
        31
        +func (q Question) Write(b *bytes.Buffer) error {

      
        
        32
        +	_ = writeName(b, q.Name)

      
        
        33
        +	_ = binary.Write(b, binary.BigEndian, q.Type)

      
        
        34
        +	_ = binary.Write(b, binary.BigEndian, q.Class)

      
        
        35
        +	return nil

      
        
        36
        +}

      
M dns-server/record.go
···
        4
        4
         	"bytes"

      
        5
        5
         	"encoding/binary"

      
        6
        6
         	"fmt"

      
        
        7
        +	"net"

      
        7
        8
         	"strings"

      
        8
        9
         )

      
        9
        10
         

      ···
        51
        52
         	}, nil

      
        52
        53
         }

      
        53
        54
         

      
        
        55
        +func (r Record) Write(b *bytes.Buffer) (int, error) {

      
        
        56
        +	start := b.Len()

      
        
        57
        +	switch r.Type {

      
        
        58
        +	case 1: // A

      
        
        59
        +		_ = writeName(b, r.Name)

      
        
        60
        +		_ = binary.Write(b, binary.BigEndian, r.Type)

      
        
        61
        +		_ = binary.Write(b, binary.BigEndian, r.Class)

      
        
        62
        +		_ = binary.Write(b, binary.BigEndian, r.TTL)

      
        
        63
        +		_ = binary.Write(b, binary.BigEndian, uint16(4))

      
        
        64
        +

      
        
        65
        +		ip := net.ParseIP(r.Data).To4()

      
        
        66
        +		if ip == nil {

      
        
        67
        +			return 0, fmt.Errorf("invalid IPv4 address: %s", r.Data)

      
        
        68
        +		}

      
        
        69
        +

      
        
        70
        +		_, _ = b.Write(ip)

      
        
        71
        +

      
        
        72
        +	default:

      
        
        73
        +		fmt.Printf("Skipping record: %+v\n", r)

      
        
        74
        +	}

      
        
        75
        +

      
        
        76
        +	return b.Len() - start, nil

      
        
        77
        +}

      
        
        78
        +

      
        54
        79
         func readName(r *bytes.Reader, packet []byte) (string, error) {

      
        55
        80
         	var labels []string

      
        56
        81
         	for {

      ···
        84
        109
         	}

      
        85
        110
         	return strings.Join(labels, "."), nil

      
        86
        111
         }

      
        
        112
        +

      
        
        113
        +// TODO: wrap the Buffer, to have the len == 512 guard

      
        
        114
        +func writeName(w *bytes.Buffer, qname string) error {

      
        
        115
        +	for label := range strings.SplitSeq(qname, ".") {

      
        
        116
        +		llen := len(label)

      
        
        117
        +		if llen > 0x3f {

      
        
        118
        +			return fmt.Errorf("single label exceeds 63 characters of length")

      
        
        119
        +		}

      
        
        120
        +		_ = w.WriteByte(byte(llen))

      
        
        121
        +		_, _ = w.Write([]byte(label))

      
        
        122
        +	}

      
        
        123
        +	_ = w.WriteByte(0)

      
        
        124
        +	return nil

      
        
        125
        +}

      
D dns-server/response_packet.txt

Not showing binary file.