Something went wrong. Try again.
forked from tailscale/tailscale
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182// Copyright (c) Tailscale Inc & contributors// SPDX-License-Identifier: BSD-3-Clause
package resolver
import ( "fmt" "html" "net/http" "strconv" "sync/atomic" "time"
"tailscale.com/feature/buildfeatures" "tailscale.com/health" "tailscale.com/syncs")
func init() { if !buildfeatures.HasDNS { return } health.RegisterDebugHandler("dnsfwd", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { n, _ := strconv.Atoi(r.FormValue("n")) if n <= 0 { n = 100 } else if n > 10000 { n = 10000 } fl := fwdLogAtomic.Load() if fl == nil || n != len(fl.ent) { fl = &fwdLog{ent: make([]fwdLogEntry, n)} fwdLogAtomic.Store(fl) } fl.ServeHTTP(w, r) }))}
var fwdLogAtomic atomic.Pointer[fwdLog]
type fwdLog struct { mu syncs.Mutex pos int // ent[pos] is next entry ent []fwdLogEntry}
type fwdLogEntry struct { Domain string Time time.Time}
func (fl *fwdLog) addName(name string) { if fl == nil { return } fl.mu.Lock() defer fl.mu.Unlock() if len(fl.ent) == 0 { return } fl.ent[fl.pos] = fwdLogEntry{Domain: name, Time: time.Now()} fl.pos++ if fl.pos == len(fl.ent) { fl.pos = 0 }}
func (fl *fwdLog) ServeHTTP(w http.ResponseWriter, r *http.Request) { fl.mu.Lock() defer fl.mu.Unlock()
fmt.Fprintf(w, "<html><h1>DNS forwards</h1>") now := time.Now() for i := range len(fl.ent) { ent := fl.ent[(i+fl.pos)%len(fl.ent)] if ent.Domain == "" { continue } fmt.Fprintf(w, "%v ago: %v<br>\n", now.Sub(ent.Time).Round(time.Second), html.EscapeString(ent.Domain)) }}