emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 8f6550b: New dns-mode command for IPv6 address conv


From: Glenn Morris
Subject: [Emacs-diffs] master 8f6550b: New dns-mode command for IPv6 address conversion
Date: Tue, 23 May 2017 20:34:28 -0400 (EDT)

branch: master
commit 8f6550b38c8b467a8f26c63050bd842f4fdc0b1e
Author: Peder O. Klingenberg <address@hidden>
Commit: Glenn Morris <address@hidden>

    New dns-mode command for IPv6 address conversion
    
    This converts IPv6 addresses to a format suitable for
    reverse lookup zone files.  (Bug#26820)
    * lisp/textmodes/dns-mode.el (dns-mode-map, dns-mode-menu):
    Add dns-mode-ipv6-to-nibbles.
    (dns-mode-ipv6-to-nibbles, dns-mode-reverse-and-expand-ipv6):
    New functions.
    * test/lisp/dns-mode-tests.el: New file.
    ; * etc/NEWS: Mention this.
---
 etc/NEWS                    |  4 ++
 lisp/textmodes/dns-mode.el  | 99 ++++++++++++++++++++++++++++++++++++++++++++-
 test/lisp/dns-mode-tests.el | 58 ++++++++++++++++++++++++++
 3 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/etc/NEWS b/etc/NEWS
index 2ca91d5..2a7c48d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -850,6 +850,10 @@ This is done with the help of 'c-or-c++-mode' function 
which analyses
 contents of the buffer to determine whether it's a C or C++ source
 file.
 
+---
+** New DNS mode command 'dns-mode-ipv6-to-nibbles' to convert IPv6 addresses
+to a format suitable for reverse lookup zone files.
+
 ** Flymake
 
 +++
diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el
index cc8bad6..7bdadbf 100644
--- a/lisp/textmodes/dns-mode.el
+++ b/lisp/textmodes/dns-mode.el
@@ -147,6 +147,7 @@ manually with \\[dns-mode-soa-increment-serial]."
 (defvar dns-mode-map
   (let ((map (make-sparse-keymap)))
     (define-key map "\C-c\C-s" 'dns-mode-soa-increment-serial)
+    (define-key map "\C-c\C-e" 'dns-mode-ipv6-to-nibbles)
     map)
   "Keymap for DNS master file mode.")
 
@@ -158,7 +159,8 @@ manually with \\[dns-mode-soa-increment-serial]."
 (easy-menu-define dns-mode-menu dns-mode-map
   "DNS Menu."
   '("DNS"
-    ["Increment SOA serial" dns-mode-soa-increment-serial t]))
+    ["Increment SOA serial" dns-mode-soa-increment-serial t]
+    ["Convert IPv6 address to nibbles" dns-mode-ipv6-to-nibbles t]))
 
 ;; Mode.
 
@@ -254,6 +256,101 @@ This function is run from `before-save-hook'."
           ;; We return nil in case this is used in write-contents-functions.
           nil)))
 
+;;;###autoload
+(defun dns-mode-ipv6-to-nibbles (&optional negate-prefix)
+  "Convert an IPv6 address around or before point.
+Replace the address by its ip6.arpa-representation for use in
+reverse zone files, placing the original address in the kill ring.
+
+The address can be: a complete address (no prefix designator);
+with a normal prefix designator (e.g. /48), in which case only
+the required number of nibbles are output; or with a negative
+prefix designator (e.g. /-112), in which case only the part of
+the address *not* covered by the absolute value of the prefix
+length is output, as a relative address (without \".ip6.arpa.\" at
+the end).  This is useful when $ORIGIN is specified in the zone file.
+
+Optional prefix argument NEGATE-PREFIX negates the value of the
+detected prefix length.
+
+Examples:
+
+2001:db8::12  =>
+2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
+
+2001:db8::12/32  =>
+8.b.d.0.1.0.0.2.ip6.arpa.
+
+2001:db8::12/-32  =>
+2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
+
+::42/112 (with prefix argument) =>
+2.4.0.0"
+  (interactive "P")
+  (skip-syntax-backward " ")
+  (skip-syntax-backward "w_.")
+  (re-search-forward "\\([[:xdigit:]:]+\\)\\(/-?[0-9]\\{2,3\\}\\)?")
+  (kill-new (match-string 0))
+  (let ((address (match-string 1))
+        (prefix-length (match-string 2)))
+    (when prefix-length
+      (setq prefix-length (string-to-number (substring prefix-length 1)))
+      (if negate-prefix
+          (setq prefix-length (- prefix-length))))
+    (replace-match
+     (save-match-data
+       (dns-mode-reverse-and-expand-ipv6 address prefix-length)))))
+
+(defun dns-mode-reverse-and-expand-ipv6 (address &optional prefix-length)
+  "Convert an IPv6 address to (parts of) an ip6.arpa nibble format.
+ADDRESS is an IPv6 address in the usual colon-separated
+format, without a prefix designator at the end.
+
+Optional PREFIX-LENGTH is a number whose absolute value is the
+length in bits of the network part of the address.  If nil,
+return an absolute address representing the full IPv6 address.
+If positive, return an absolute address representing the network
+prefix indicated.  If negative, return a relative address
+representing the host parts of the address with respect to the
+indicated network prefix.
+
+See `dns-mode-ipv6-to-nibbles' for examples."
+  (let* ((chunks (split-string address ":"))
+         (prefix-length-nibbles (if prefix-length
+                                    (ceiling (abs prefix-length) 4)
+                                  32))
+         (filler-chunks (- 8 (length (remove "" chunks))))
+         (expanded-address
+          (apply #'concat
+                 (cl-loop with filler-done = nil
+                          for chunk in chunks
+                          if (and (not filler-done)
+                                  (string= "" chunk))
+                          append (prog1
+                                     (cl-loop repeat filler-chunks
+                                              collect "0000")
+                                   (setq filler-done t))
+                          else
+                          if (not (string= "" chunk))
+                          collect (format "%04x"
+                                          (string-to-number chunk 16)))))
+         (rev-address-nibbles
+          (nreverse (if (and prefix-length
+                             (cl-minusp prefix-length))
+                        (substring expanded-address prefix-length-nibbles)
+                      (substring expanded-address 0 prefix-length-nibbles)))))
+    (with-temp-buffer
+      (cl-loop for char across rev-address-nibbles
+               do
+               (insert char)
+               (insert "."))
+      (if (and prefix-length
+               (cl-minusp prefix-length))
+          (delete-char -1)
+        (insert "ip6.arpa."))
+      (insert " ")
+      (buffer-string))))
+
 (provide 'dns-mode)
 
 ;;; dns-mode.el ends here
diff --git a/test/lisp/dns-mode-tests.el b/test/lisp/dns-mode-tests.el
new file mode 100644
index 0000000..34e8620
--- /dev/null
+++ b/test/lisp/dns-mode-tests.el
@@ -0,0 +1,58 @@
+;;; dns-mode-tests.el --- Test suite for dns-mode  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; Author: Peder O. Klingenberg <address@hidden>
+;; Keywords: dns zone
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'dns-mode)
+
+;;; IPv6 reverse zones
+(ert-deftest dns-mode-ipv6-conversion ()
+  (let ((address "2001:db8::42"))
+    (should (equal (dns-mode-reverse-and-expand-ipv6 address)
+                   
"2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. "))
+    (should (equal (dns-mode-reverse-and-expand-ipv6 address 32)
+                   "8.b.d.0.1.0.0.2.ip6.arpa. "))
+    (should (equal (dns-mode-reverse-and-expand-ipv6 address -112)
+                   "2.4.0.0 "))))
+
+(ert-deftest dns-mode-ipv6-text-replacement ()
+  (let ((address "2001:db8::42/32"))
+    (with-temp-buffer
+      ;; Conversion with point directly after address
+      (insert address)
+      (dns-mode-ipv6-to-nibbles nil)
+      (should (equal (buffer-string) "8.b.d.0.1.0.0.2.ip6.arpa. "))
+      ;; Kill ring contains the expected
+      (erase-buffer)
+      (yank)
+      (should (equal (buffer-string) address))
+      ;; Point at beginning of address (and prefix arg to command)
+      (goto-char (point-min))
+      (dns-mode-ipv6-to-nibbles t)
+      (should (equal (buffer-string) 
"2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 "))
+      ;; Point separated from address by whitespace
+      (erase-buffer)
+      (insert address)
+      (insert " ")
+      (dns-mode-ipv6-to-nibbles nil)
+      (should (equal (buffer-string) "8.b.d.0.1.0.0.2.ip6.arpa.  ")))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]