diff --git a/dist/tools/headerguards/check.sh b/dist/tools/headerguards/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a3ba4f0d45a05cd7edff6aba7ad06ef62dfdcddf
--- /dev/null
+++ b/dist/tools/headerguards/check.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# Copyright 2017 Kaspar Schleiser <kaspar@schleiser.de>
+#
+# This file is subject to the terms and conditions of the GNU Lesser
+# General Public License v2.1. See the file LICENSE in the top level
+# directory for more details.
+
+: ${RIOTBASE:=$(pwd)}
+
+. ${RIOTBASE}/dist/tools/ci/changed_files.sh
+
+EXIT_CODE=0
+
+filter() {
+    if [ $QUIET -eq 0 ]; then
+        cat
+    else
+        grep '^---' | cut -f 2 -d ' '
+    fi
+}
+
+_headercheck() {
+    OUT="$(${RIOTBASE}/dist/tools/headerguards/headerguards.py ${FILES} | filter)"
+
+    if [ -n "$OUT" ]; then
+        EXIT_CODE=1
+        echo "$OUT"
+    fi
+}
+
+: ${FILES:=$(FILEREGEX='\.h$' changed_files)}
+
+if [ -z "${FILES}" ]; then
+    exit
+fi
+
+: ${QUIET:=0}
+
+if [ -z "$*" ]; then
+    _headercheck
+fi
+
+exit $EXIT_CODE
diff --git a/dist/tools/headerguards/headerguards.py b/dist/tools/headerguards/headerguards.py
new file mode 100755
index 0000000000000000000000000000000000000000..7affa3bd4fb2cb62c1738bcaaf4eb82fb284a910
--- /dev/null
+++ b/dist/tools/headerguards/headerguards.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+
+import os, sys
+import difflib
+#from string import maketrans
+from io import BytesIO, TextIOWrapper
+
+_in = "/-."
+_out = "___"
+
+transtab = str.maketrans(_in, _out)
+
+def path_to_guardname(filepath):
+    res = filepath.upper().translate(transtab)
+    if res.startswith("_"):
+        res = "PRIV" + res
+    return res
+
+def get_guard_name(filepath):
+    parts = filepath.split(os.sep)
+    start = 0
+    found = False
+    for i, part in enumerate(parts):
+        if part == "include":
+            found = True
+            start = i+1
+            break
+
+    if not found:
+        start = len(parts) -1
+
+    return path_to_guardname(os.path.join(*parts[start:]))
+
+def fix_headerguard(filename):
+    supposed = get_guard_name(filename)
+    with open(filename, "r",encoding='utf-8', errors='ignore') as f:
+        inlines = f.readlines()
+
+    tmp = TextIOWrapper(BytesIO(), encoding="utf-8", errors="ignore")
+    tmp.seek(0)
+
+    guard_found = 0
+    guard_name = ""
+    ifstack = 0
+    for n, line in enumerate(inlines):
+        if guard_found == 0:
+            if line.startswith("#ifndef"):
+                guard_found += 1
+                guard_name = line[8:].rstrip()
+                line = "#ifndef %s\n" % (supposed)
+        elif guard_found == 1:
+            if line.startswith("#define") and line[8:].rstrip() == guard_name:
+                line = "#define %s\n" % (supposed)
+                guard_found += 1
+            else:
+                break
+        elif guard_found == 2:
+            if line.startswith("#if"):
+                ifstack += 1
+            elif line.startswith("#endif"):
+                if ifstack > 0:
+                    ifstack -= 1
+                else:
+                    guard_found += 1
+                    line = "#endif /* %s */\n" % supposed
+
+        tmp.write(line)
+
+    tmp.seek(0)
+    if guard_found == 3:
+        for line in difflib.unified_diff(inlines, tmp.readlines(), "%s" % filename, "%s" % filename):
+            sys.stdout.write(line)
+    else:
+        print("%s: no / broken header guard" % filename, file=sys.stderr)
+        return False
+
+if __name__=="__main__":
+    error = False
+    for filename in sys.argv[1:]:
+        if fix_headerguard(filename) == False:
+            error = True
+
+    if error:
+        sys.exit(1)