summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_doc/resolver.adoc20
-rw-r--r--_sys/usr/share/man/man1/resolver.1.gzbin3508 -> 3596 bytes
-rw-r--r--client.go46
-rw-r--r--cmd/resolver/resolver.go105
-rw-r--r--httpd.go45
5 files changed, 192 insertions, 24 deletions
diff --git a/_doc/resolver.adoc b/_doc/resolver.adoc
index 362bc62..d2d96c5 100644
--- a/_doc/resolver.adoc
+++ b/_doc/resolver.adoc
@@ -245,6 +245,13 @@ we pass two parameters:
See the example below for more information.
--
+`zone.d rr delete <zone> <"@" | subdomain> <type> <class> <value>`::
++
+--
+Delete record from zone by its subdomain, type, class, and value.
+--
+
+
== EXIT STATUS
Upon exit and success +resolver+ will return 0, or 1 otherwise.
@@ -394,6 +401,10 @@ Get all records in the zone "my.zone",
Add IPv4 address "127.0.0.1" for domain my.zone,
$ resolver zone.d rr add my.zone @ 0 A IN 127.0.0.1
+
+or
+
+ $ resolver zone.d rr add my.zone "" 0 A IN 127.0.0.1
{
"Value": "127.0.0.1",
"Name": "my.zone",
@@ -402,6 +413,11 @@ Add IPv4 address "127.0.0.1" for domain my.zone,
"TTL": 604800
}
+and to delete the above record,
+
+ $ resolver zone.d rr delete my.zone @ A IN 127.0.0.1
+ OK
+
Add subdomain "www" with IPv4 address "192.168.1.2" to zone "my.zone",
$ resolver zone.d rr add my.zone www 0 A IN 192.168.1.2
@@ -413,6 +429,10 @@ Add subdomain "www" with IPv4 address "192.168.1.2" to zone "my.zone",
"TTL": 604800
}
+and to delete the above record,
+
+ $ resolver zone.d rr delete my.zone www A IN 192.168.1.2
+ OK
== AUTHOR
diff --git a/_sys/usr/share/man/man1/resolver.1.gz b/_sys/usr/share/man/man1/resolver.1.gz
index a3b628c..38963de 100644
--- a/_sys/usr/share/man/man1/resolver.1.gz
+++ b/_sys/usr/share/man/man1/resolver.1.gz
Binary files differ
diff --git a/client.go b/client.go
index ca1297c..24e7fb6 100644
--- a/client.go
+++ b/client.go
@@ -570,3 +570,49 @@ func (cl *Client) ZonedRecordAdd(name string, rreq dns.ResourceRecord) (rres *dn
return rres, nil
}
+
+// ZonedRecordDelete delete record from zone file.
+func (cl *Client) ZonedRecordDelete(name string, rreq dns.ResourceRecord) (zoneRecords dns.ZoneRecords, err error) {
+ var (
+ logp = "ZonedRecordDelete"
+ params = url.Values{}
+
+ res *libhttp.EndpointResponse
+ vstr string
+ rawb []byte
+ ok bool
+ )
+
+ params.Set(paramNameName, name)
+
+ vstr, ok = dns.RecordTypeNames[rreq.Type]
+ if !ok {
+ return nil, fmt.Errorf("%s: unknown record type: %d", logp, rreq.Type)
+ }
+ params.Set(paramNameType, vstr)
+
+ rawb, err = json.Marshal(rreq)
+ if err != nil {
+ return nil, fmt.Errorf("%s: %w", logp, err)
+ }
+ vstr = base64.StdEncoding.EncodeToString(rawb)
+ params.Set(paramNameRecord, vstr)
+
+ _, rawb, err = cl.Delete(apiZonedRR, nil, params)
+ if err != nil {
+ return nil, fmt.Errorf("%s: %w", logp, err)
+ }
+
+ res = &libhttp.EndpointResponse{
+ Data: &zoneRecords,
+ }
+ err = json.Unmarshal(rawb, res)
+ if err != nil {
+ return nil, fmt.Errorf("%s: %w", logp, err)
+ }
+ if res.Code != http.StatusOK {
+ return nil, fmt.Errorf("%s: %d %s", logp, res.Code, res.Message)
+ }
+
+ return zoneRecords, nil
+}
diff --git a/cmd/resolver/resolver.go b/cmd/resolver/resolver.go
index ead3cfc..b22bee1 100644
--- a/cmd/resolver/resolver.go
+++ b/cmd/resolver/resolver.go
@@ -534,16 +534,18 @@ func (rsol *resolver) doCmdZonedRR(resc *rescached.Client, args []string) {
}
var (
- cmdAction string
+ cmdAction = strings.ToLower(args[0])
)
- cmdAction = strings.ToLower(args[0])
args = args[1:]
switch cmdAction {
case subCmdAdd:
rsol.doCmdZonedRRAdd(resc, args)
+ case subCmdDelete:
+ rsol.doCmdZonedRRDelete(resc, args)
+
case subCmdGet:
rsol.doCmdZonedRRGet(resc, args)
@@ -636,6 +638,72 @@ func (rsol *resolver) doCmdZonedRRAdd(resc *rescached.Client, args []string) {
fmt.Println(string(vbytes))
}
+// doCmdZonedRRDelete delete record from zone.
+// This command accept the following arguments:
+//
+// 0 1 2 3 4
+// <zone> <domain> <type> <class> <value> ...
+func (rsol *resolver) doCmdZonedRRDelete(resc *rescached.Client, args []string) {
+ if len(args) < 5 {
+ log.Fatalf("resolver: %s %s %s: missing arguments", rsol.cmd, subCmdRR, subCmdDelete)
+ }
+
+ var (
+ zone = strings.ToLower(args[0])
+ rreq = dns.ResourceRecord{}
+
+ zoneRecords dns.ZoneRecords
+ vstr string
+ vuint uint64
+ err error
+ ok bool
+ )
+
+ rreq.Name = strings.ToLower(args[1])
+ if rreq.Name == "@" {
+ rreq.Name = ""
+ }
+
+ vstr = strings.ToUpper(args[2])
+ rreq.Type, ok = dns.RecordTypes[vstr]
+ if !ok {
+ log.Fatalf("resolver: invalid record type: %q", vstr)
+ }
+
+ vstr = strings.ToUpper(args[3])
+ rreq.Class, ok = dns.RecordClasses[vstr]
+ if !ok {
+ log.Fatalf("resolver: invalid record class: %q", vstr)
+ }
+
+ vstr = args[4]
+
+ if rreq.Type == dns.RecordTypeMX {
+ if len(args) < 5 {
+ log.Fatalf("resolver: missing argument for MX record")
+ }
+ vuint, err = strconv.ParseUint(vstr, 10, 64)
+ if err != nil {
+ log.Fatalf("resolver: invalid MX preference: %q", vstr)
+ }
+ var rrMX = &dns.RDataMX{
+ Preference: int16(vuint),
+ Exchange: args[5],
+ }
+ rreq.Value = rrMX
+ } else {
+ rreq.Value = vstr
+ }
+
+ zoneRecords, err = resc.ZonedRecordDelete(zone, rreq)
+ if err != nil {
+ log.Fatalf("resolver: %s", err)
+ }
+
+ fmt.Println("OK")
+ printZoneRecords(zoneRecords)
+}
+
// doCmdZonedRRGet get and print the records on zone.
func (rsol *resolver) doCmdZonedRRGet(resc *rescached.Client, args []string) {
if len(args) == 0 {
@@ -644,9 +712,6 @@ func (rsol *resolver) doCmdZonedRRGet(resc *rescached.Client, args []string) {
var (
zoneRecords dns.ZoneRecords
- dname string
- listRR []*dns.ResourceRecord
- rr *dns.ResourceRecord
err error
)
@@ -655,16 +720,7 @@ func (rsol *resolver) doCmdZonedRRGet(resc *rescached.Client, args []string) {
log.Fatalf("resolver: %s", err)
}
- for dname, listRR = range zoneRecords {
- fmt.Println(dname)
- for _, rr = range listRR {
- fmt.Printf(" %6d %2s %2s %v\n",
- rr.TTL,
- dns.RecordTypeNames[rr.Type],
- dns.RecordClassName[rr.Class],
- rr.Value)
- }
- }
+ printZoneRecords(zoneRecords)
}
// initSystemResolver read the system resolv.conf to create fallback DNS
@@ -843,3 +899,22 @@ func printQueryResponse(nameserver string, msg *dns.Message) {
fmt.Println(b.String())
printMessage(msg)
}
+
+func printZoneRecords(zr dns.ZoneRecords) {
+ var (
+ dname string
+ listRR []*dns.ResourceRecord
+ rr *dns.ResourceRecord
+ )
+
+ for dname, listRR = range zr {
+ fmt.Println(dname)
+ for _, rr = range listRR {
+ fmt.Printf(" %6d %2s %2s %v\n",
+ rr.TTL,
+ dns.RecordTypeNames[rr.Type],
+ dns.RecordClassName[rr.Class],
+ rr.Value)
+ }
+ }
+}
diff --git a/httpd.go b/httpd.go
index c74717b..3c819bf 100644
--- a/httpd.go
+++ b/httpd.go
@@ -1301,14 +1301,19 @@ func (srv *Server) apiZonedRRAdd(epr *libhttp.EndpointRequest) (resb []byte, err
// # Response
//
// On success it will return all the records in the zone.
+//
+// On fail it will return,
+// - 400: if one of the parameter is invalid or empty.
+// - 404: if the record to be deleted not found.
func (srv *Server) apiZonedRRDelete(epr *libhttp.EndpointRequest) (resbody []byte, err error) {
var (
res = libhttp.EndpointResponse{}
req = zoneRecordRequest{}
- rr = dns.ResourceRecord{}
+ rr = &dns.ResourceRecord{}
- zone *dns.Zone
- ok bool
+ zone *dns.Zone
+ rrValue string
+ ok bool
)
res.Code = http.StatusBadRequest
@@ -1344,27 +1349,49 @@ func (srv *Server) apiZonedRRDelete(epr *libhttp.EndpointRequest) (resbody []byt
rr.Value = &dns.RDataSOA{}
case dns.RecordTypeMX:
rr.Value = &dns.RDataMX{}
+ default:
+ rr.Value = rrValue
}
- err = json.Unmarshal(req.recordRaw, &rr)
+ err = json.Unmarshal(req.recordRaw, rr)
if err != nil {
res.Message = "json.Unmarshal: " + err.Error()
return nil, &res
}
- if len(rr.Name) == 0 {
- res.Message = "invalid or empty ResourceRecord.Name"
- return nil, &res
+ rr.Name = strings.TrimRight(rr.Name, ".")
+
+ if rr.Type == dns.RecordTypePTR {
+ if len(rr.Name) == 0 {
+ res.Message = "empty PTR name"
+ return nil, &res
+ }
+ if len(rrValue) == 0 {
+ rr.Value = req.Name
+ } else {
+ rr.Value = rrValue + "." + req.Name
+ }
+ } else {
+ if len(rr.Name) == 0 {
+ rr.Name = req.Name
+ } else {
+ rr.Name += "." + req.Name
+ }
}
// Remove the RR from caches.
- err = srv.dns.RemoveCachesByRR(&rr)
+ rr, err = srv.dns.RemoveCachesByRR(rr)
if err != nil {
res.Message = err.Error()
return nil, &res
}
+ if rr == nil {
+ res.Code = http.StatusNotFound
+ res.Message = "record not found"
+ return nil, &res
+ }
// Remove the RR from zone file.
- err = zone.Remove(&rr)
+ err = zone.Remove(rr)
if err != nil {
res.Message = err.Error()
return nil, &res