diff --git a/sys/include/net/gnrc/rpl/srh.h b/sys/include/net/gnrc/rpl/srh.h
index ab7248d2308f78690d77e27763c303e725d9993b..21fce7fe123e4af8b9d0a94c4d4370f067fb2f8d 100644
--- a/sys/include/net/gnrc/rpl/srh.h
+++ b/sys/include/net/gnrc/rpl/srh.h
@@ -52,6 +52,10 @@ typedef struct __attribute__((packed)) {
 /**
  * @brief   Process the RPL source routing header.
  *
+ * @pre `rh->seq_left > 0`; The 0 case means the destination is reached and
+ *      common among all routing headers, so it should be handled by an
+ *      external routing header handler.
+ *
  * @param[in,out] ipv6  The IPv6 header of the incoming packet.
  * @param[in] rh        A RPL source routing header.
  *
diff --git a/sys/net/gnrc/routing/rpl/srh/gnrc_rpl_srh.c b/sys/net/gnrc/routing/rpl/srh/gnrc_rpl_srh.c
index 753d5bf65e0b9255e0808e7a433c1f119d3b5d92..618d749a1a3ae106f863cbc869e76ace9db9c191 100644
--- a/sys/net/gnrc/routing/rpl/srh/gnrc_rpl_srh.c
+++ b/sys/net/gnrc/routing/rpl/srh/gnrc_rpl_srh.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
+ * Copyright (C) 2015 Cenk Gündoğan <cnkgndgn@gmail.com>
+ * Copyright (C) 2018 Freie Universität Berlin
  *
  * 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
@@ -10,6 +11,8 @@
  * @{
  *
  * @file
+ * @author Cenk Gündoğan <cnkgndgn@gmail.com>
+ * @author Martine Lenders <m.lenders@fu-berlin.de>
  */
 
 #include <string.h>
@@ -26,34 +29,74 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN];
 #define GNRC_RPL_SRH_COMPRE(X)      (X & 0x0F)
 #define GNRC_RPL_SRH_COMPRI(X)      ((X & 0xF0) >> 4)
 
-int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
+/* checks if multiple addresses within the source routing header exist on my
+ * interfaces */
+static bool _contains_multiple_of_my_addr(const ipv6_addr_t *dst,
+                                          const gnrc_rpl_srh_t *rh,
+                                          unsigned num_addr,
+                                          unsigned compri_addr_len)
 {
-    if (rh->seg_left == 0) {
-        return GNRC_IPV6_EXT_RH_AT_DST;
+    ipv6_addr_t addr;
+    uint8_t *addr_vec = (uint8_t *) (rh + 1);
+    bool found = false;
+    uint8_t pref_elided = GNRC_RPL_SRH_COMPRI(rh->compr);
+    uint8_t addr_len = compri_addr_len;
+    uint8_t found_pos = 0;
+
+    memcpy(&addr, dst, pref_elided);
+    for (unsigned i = 0; i < num_addr; i++) {
+        if (i == num_addr - 1) {
+            pref_elided = GNRC_RPL_SRH_COMPRE(rh->compr);
+            addr_len = sizeof(ipv6_addr_t) - pref_elided;
+        }
+        memcpy(&addr.u8[pref_elided], &addr_vec[i * compri_addr_len], addr_len);
+        if (gnrc_netif_get_by_ipv6_addr(&addr) != NULL) {
+            if (found && ((i - found_pos) > 1)) {
+                DEBUG("RPL SRH: found multiple addresses that belong to me - "
+                      "discard\n");
+                /* TODO send an ICMP Parameter Problem (Code 0) and
+                 * discard the packet */
+                return true;
+            }
+            found_pos = i;
+            found = true;
+        }
     }
+    return false;
+}
 
-    uint8_t n = (((rh->len * 8) - GNRC_RPL_SRH_PADDING(rh->pad_resv) -
-                 (16 - GNRC_RPL_SRH_COMPRE(rh->compr))) /
-                 (16 - GNRC_RPL_SRH_COMPRI(rh->compr))) + 1;
-    ipv6_addr_t addr = ipv6->dst, tmp;
-    uint8_t i, pref_elided, tmp_pref_elided, addr_len, compri_addr_len, tmp_addr_len, found_pos = 0;
+int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
+{
+    ipv6_addr_t addr;
     uint8_t *addr_vec = (uint8_t *) (rh + 1);
-    bool found = false;
+    uint8_t num_addr;
+    uint8_t current_pos, pref_elided, addr_len, compri_addr_len;
+    const uint8_t new_seg_left = rh->seg_left - 1;
 
-    DEBUG("RPL SRH: %u addresses in the routing header\n", (unsigned) n);
+    assert(rh->seg_left > 0);
+    num_addr = (((rh->len * 8) - GNRC_RPL_SRH_PADDING(rh->pad_resv) -
+                 (16 - GNRC_RPL_SRH_COMPRE(rh->compr))) /
+                (16 - GNRC_RPL_SRH_COMPRI(rh->compr))) + 1;
 
-    if (rh->seg_left > n) {
-        DEBUG("RPL SRH: number of segments left > number of addresses - discard\n");
+    DEBUG("RPL SRH: %u addresses in the routing header\n", (unsigned) num_addr);
+
+    if (rh->seg_left > num_addr) {
+        DEBUG("RPL SRH: number of segments left > number of addresses - "
+              "discard\n");
         /* TODO ICMP Parameter Problem - Code 0 */
         return GNRC_IPV6_EXT_RH_ERROR;
     }
 
-    rh->seg_left--;
-    i = n - rh->seg_left;
-    pref_elided = rh->seg_left ? GNRC_RPL_SRH_COMPRI(rh->compr) : GNRC_RPL_SRH_COMPRE(rh->compr);
+    current_pos = num_addr - new_seg_left;
+    pref_elided = (new_seg_left)
+                ? GNRC_RPL_SRH_COMPRI(rh->compr)
+                : GNRC_RPL_SRH_COMPRE(rh->compr);
     compri_addr_len = sizeof(ipv6_addr_t) - GNRC_RPL_SRH_COMPRI(rh->compr);
     addr_len = sizeof(ipv6_addr_t) - pref_elided;
-    memcpy(&addr.u8[pref_elided], &addr_vec[(i - 1) * compri_addr_len], addr_len);
+    memcpy(&addr, &ipv6->dst, pref_elided);
+    memcpy(&addr.u8[pref_elided],
+           &addr_vec[(current_pos - 1) * compri_addr_len],
+           addr_len);
 
     if (ipv6_addr_is_multicast(&ipv6->dst) || ipv6_addr_is_multicast(&addr)) {
         DEBUG("RPL SRH: found a multicast address - discard\n");
@@ -62,32 +105,18 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
     }
 
     /* check if multiple addresses of my interface exist */
-    tmp_pref_elided = GNRC_RPL_SRH_COMPRI(rh->compr);
-    tmp_addr_len = sizeof(ipv6_addr_t) - tmp_pref_elided;
-    tmp = ipv6->dst;
-    for (uint8_t k = 0; k < n; k++) {
-        if (k == n - 1) {
-            tmp_pref_elided = GNRC_RPL_SRH_COMPRE(rh->compr);
-            tmp_addr_len = sizeof(ipv6_addr_t) - tmp_pref_elided;
-        }
-        memcpy(&tmp.u8[tmp_pref_elided], &addr_vec[k * compri_addr_len], tmp_addr_len);
-        if (gnrc_netif_get_by_ipv6_addr(&tmp) != NULL) {
-            if (found && ((k - found_pos) > 1)) {
-                DEBUG("RPL SRH: found multiple addresses that belong to me - discard\n");
-                /* TODO send an ICMP Parameter Problem (Code 0) and discard the packet */
-                return GNRC_IPV6_EXT_RH_ERROR;
-            }
-            found_pos = k;
-            found = true;
-        }
+    if (_contains_multiple_of_my_addr(&ipv6->dst, rh, num_addr,
+                                      compri_addr_len)) {
+        return GNRC_IPV6_EXT_RH_ERROR;
     }
-
-    memcpy(&addr_vec[(i - 1) * compri_addr_len], &ipv6->dst.u8[pref_elided], addr_len);
+    rh->seg_left = new_seg_left;
+    memcpy(&addr_vec[(current_pos - 1) * compri_addr_len],
+           &ipv6->dst.u8[pref_elided], addr_len);
 
     DEBUG("RPL SRH: Next hop: %s at position %d\n",
-          ipv6_addr_to_str(addr_str, &addr, sizeof(addr_str)), i);
+          ipv6_addr_to_str(addr_str, &addr, sizeof(addr_str)), current_pos);
 
-    ipv6->dst = addr;
+    memcpy(&ipv6->dst, &addr, sizeof(ipv6->dst));
 
     return GNRC_IPV6_EXT_RH_FORWARDED;
 }