mirror of
https://github.com/soypat/lneto.git
synced 2026-08-25 08:59:05 +00:00
work on httpraw normalization and dns/dhcp bridge example
This commit is contained in:
+11
-1
@@ -267,6 +267,16 @@ func (c *Client) reset(xid uint32) {
|
|||||||
|
|
||||||
func (d *Client) State() ClientState { return d.state }
|
func (d *Client) State() ClientState { return d.state }
|
||||||
|
|
||||||
|
func (d *Client) BroadcastAddr() [4]byte { return d.broadcast }
|
||||||
|
func (d *Client) AssignedAddr() [4]byte { return d.offer }
|
||||||
|
func (d *Client) ServerAddr() [4]byte { return d.svip }
|
||||||
|
func (d *Client) RouterAddr() [4]byte { return d.router }
|
||||||
|
func (d *Client) GatewayAddr() [4]byte { return d.gateway }
|
||||||
|
func (d *Client) RebindingSeconds() uint32 { return d.tRebind }
|
||||||
|
func (d *Client) RenewalSeconds() uint32 { return d.tRenew }
|
||||||
|
func (d *Client) IPLeaseSeconds() uint32 { return d.tIPLease }
|
||||||
|
func (d *Client) AppendDNSServers(dst [][4]byte) [][4]byte { return append(dst, d.dns...) }
|
||||||
|
|
||||||
func (d *Client) CIDRBits() uint8 {
|
func (d *Client) CIDRBits() uint8 {
|
||||||
if d.subnet == [4]byte{} {
|
if d.subnet == [4]byte{} {
|
||||||
return 0
|
return 0
|
||||||
@@ -287,7 +297,7 @@ var defaultParamReqList = []byte{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func maybeU32(b []byte) uint32 {
|
func maybeU32(b []byte) uint32 {
|
||||||
if len(b) < 4 {
|
if len(b) != 4 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return binary.BigEndian.Uint32(b)
|
return binary.BigEndian.Uint32(b)
|
||||||
|
|||||||
+46
-5
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@@ -33,12 +34,19 @@ func main() {
|
|||||||
|
|
||||||
func run() (err error) {
|
func run() (err error) {
|
||||||
var (
|
var (
|
||||||
flagInterface = "tap0"
|
flagInterface = "tap0"
|
||||||
flagUseHTTP = false
|
flagUseHTTP = false
|
||||||
|
flagHostToResolve = ""
|
||||||
)
|
)
|
||||||
flag.StringVar(&flagInterface, "i", flagInterface, "Interface to use. Either tap* or the name of an existing interface to bridge to.")
|
flag.StringVar(&flagInterface, "i", flagInterface, "Interface to use. Either tap* or the name of an existing interface to bridge to.")
|
||||||
flag.BoolVar(&flagUseHTTP, "http", flagUseHTTP, "Use HTTP tap interface.")
|
flag.BoolVar(&flagUseHTTP, "http", flagUseHTTP, "Use HTTP tap interface.")
|
||||||
|
flag.StringVar(&flagHostToResolve, "host", flagHostToResolve, "Hostname to resolve via DNS.")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
_, err = dns.NewName(flagHostToResolve)
|
||||||
|
if err != nil {
|
||||||
|
flag.Usage()
|
||||||
|
return err
|
||||||
|
}
|
||||||
var iface ltesto.Interface
|
var iface ltesto.Interface
|
||||||
if flagUseHTTP {
|
if flagUseHTTP {
|
||||||
iface = ltesto.NewHTTPTapClient("http://127.0.0.1:7070")
|
iface = ltesto.NewHTTPTapClient("http://127.0.0.1:7070")
|
||||||
@@ -87,7 +95,26 @@ func run() (err error) {
|
|||||||
buf := make([]byte, mtu)
|
buf := make([]byte, mtu)
|
||||||
var iframes []pcap.Frame
|
var iframes []pcap.Frame
|
||||||
lastAction := time.Now()
|
lastAction := time.Now()
|
||||||
|
dnsOngoing := false
|
||||||
for {
|
for {
|
||||||
|
dhcpIsDone := stack.dhcp.State() == dhcpv4.StateBound
|
||||||
|
if dhcpIsDone {
|
||||||
|
if !dnsOngoing {
|
||||||
|
err = stack.StartLookupIP(flagHostToResolve)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dnsOngoing = true
|
||||||
|
} else {
|
||||||
|
addrs, err := stack.ResultLookupIP()
|
||||||
|
if err == nil {
|
||||||
|
// END PROGRAM.
|
||||||
|
fmt.Println(flagHostToResolve, "resolved to", addrs)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = dhcpIsDone
|
||||||
clear(buf)
|
clear(buf)
|
||||||
nwrite, err := stack.Encapsulate(buf[:], 0)
|
nwrite, err := stack.Encapsulate(buf[:], 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -226,9 +253,23 @@ func (s *Stack) StartLookupIP(host string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) ResultLookupIP() ([]netip.Addr, error) {
|
func (s *Stack) ResultLookupIP() ([]netip.Addr, error) {
|
||||||
s.dns.MessageCopyTo()
|
done, err := s.dns.MessageCopyTo(&s.lookup)
|
||||||
// s.dns.Answers()
|
if err != nil {
|
||||||
return nil, nil
|
return nil, err
|
||||||
|
} else if !done {
|
||||||
|
return nil, errors.New("DNS not done")
|
||||||
|
}
|
||||||
|
var addrs []netip.Addr
|
||||||
|
ans := s.lookup.Answers
|
||||||
|
for i := range ans {
|
||||||
|
data := ans[i].RawData()
|
||||||
|
if len(data) == 4 {
|
||||||
|
addrs = append(addrs, netip.AddrFrom4([4]byte(data)))
|
||||||
|
} else if len(data) == 16 {
|
||||||
|
addrs = append(addrs, netip.AddrFrom16([16]byte(data)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) BeginDHCPRequest() error {
|
func (s *Stack) BeginDHCPRequest() error {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package httpraw
|
package httpraw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -404,3 +405,82 @@ type noCopy struct{}
|
|||||||
|
|
||||||
func (*noCopy) Lock() {}
|
func (*noCopy) Lock() {}
|
||||||
func (*noCopy) Unlock() {}
|
func (*noCopy) Unlock() {}
|
||||||
|
|
||||||
|
// NormalizeKey normalizes a HTTP header key in-place. Returns true if buffer modified.
|
||||||
|
// Examples of normalization:
|
||||||
|
// - CONTENT -> Content
|
||||||
|
// - content-length -> Content-Length
|
||||||
|
// - cOnTeNt-LenGtH -> Content-Length
|
||||||
|
func NormalizeHeaderKey(b []byte) (modified bool) {
|
||||||
|
const asciiCapDiff = 'a' - 'A'
|
||||||
|
for i := -1; i < len(b); i++ {
|
||||||
|
ch := b[i]
|
||||||
|
nextToUpper := i == -1 || (ch == '-' && i < len(b)-1)
|
||||||
|
if nextToUpper {
|
||||||
|
i++
|
||||||
|
isLower := b[i] >= 'a' && b[i] <= 'z'
|
||||||
|
if isLower {
|
||||||
|
modified = true
|
||||||
|
b[i] -= asciiCapDiff
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isUpper := b[i] >= 'A' && b[i] <= 'Z'
|
||||||
|
if isUpper {
|
||||||
|
modified = true
|
||||||
|
b[i] += asciiCapDiff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modified
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyNormalizedHeaderValue copies the header value in the value buffer to dst.
|
||||||
|
// The result may be shrunk. The target and source buffers can only alias if the
|
||||||
|
// destination buffer 0 address is equal to value's 0 address.
|
||||||
|
// Header value normalization implies the replacement of \r\n\t with a single space.
|
||||||
|
func CopyNormalizedHeaderValue(dst []byte, value []byte) (n int, modified bool) {
|
||||||
|
if len(dst) < len(value) {
|
||||||
|
panic("httpraw.CopyNormalizedHeaderValue: dst buffer shorter than length")
|
||||||
|
}
|
||||||
|
lineStart := false
|
||||||
|
write := 0
|
||||||
|
read := 0
|
||||||
|
for {
|
||||||
|
rmStart := bytes.IndexByte(value[read:], '\n')
|
||||||
|
if rmStart < 0 {
|
||||||
|
write += copy(dst[write:], value[read:])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
omit := 1
|
||||||
|
rmStart += read
|
||||||
|
if rmStart > 0 && value[rmStart] == '\r' {
|
||||||
|
rmStart--
|
||||||
|
omit++
|
||||||
|
}
|
||||||
|
|
||||||
|
if rmStart+1 < len(value) && value[rmStart+1] == '\t' {
|
||||||
|
omit++
|
||||||
|
}
|
||||||
|
n := copy(dst[write:], value[:rmStart])
|
||||||
|
read += omit + n
|
||||||
|
write += n
|
||||||
|
}
|
||||||
|
return write, modified
|
||||||
|
for read := 0; read < len(value); read++ {
|
||||||
|
c := value[read]
|
||||||
|
switch {
|
||||||
|
case c == '\r' || c == '\n':
|
||||||
|
lineStart = c == '\n'
|
||||||
|
continue
|
||||||
|
case lineStart && c == '\t':
|
||||||
|
c = ' '
|
||||||
|
modified = true
|
||||||
|
default:
|
||||||
|
lineStart = false
|
||||||
|
}
|
||||||
|
dst[write] = c
|
||||||
|
write++
|
||||||
|
}
|
||||||
|
modified = modified || n != len(value)
|
||||||
|
return write, modified
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user