diff --git a/sys/include/net/gnrc/rpl/srh.h b/sys/include/net/gnrc/rpl/srh.h
index 21fce7fe123e4af8b9d0a94c4d4370f067fb2f8d..42ff83b5e691bb412d80112106df061a629b1bc2 100644
--- a/sys/include/net/gnrc/rpl/srh.h
+++ b/sys/include/net/gnrc/rpl/srh.h
@@ -56,14 +56,18 @@ typedef struct __attribute__((packed)) {
  *      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, out] ipv6 The IPv6 header of the incoming packet.
  * @param[in] rh        A RPL source routing header.
+ * @param[out] err_ptr  A pointer to an erroneous octet within @p rh when
+ *                      return value is @ref GNRC_IPV6_EXT_RH_ERROR. For any
+ *                      other return value than @ref GNRC_IPV6_EXT_RH_ERROR the
+ *                      value of `err_ptr` is not defined.
  *
  * @return  @ref GNRC_IPV6_EXT_RH_AT_DST, on success
  * @return  @ref GNRC_IPV6_EXT_RH_FORWARDED, when @p pkt *should be* forwarded
  * @return  @ref GNRC_IPV6_EXT_RH_ERROR, on error
  */
-int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh);
+int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh, void **err_ptr);
 
 #ifdef __cplusplus
 }
diff --git a/sys/net/gnrc/network_layer/ipv6/ext/rh/gnrc_ipv6_ext_rh.c b/sys/net/gnrc/network_layer/ipv6/ext/rh/gnrc_ipv6_ext_rh.c
index 68d0c2b7e583bcf780bb19f37f93d6cdf37dadb3..8a56bad75656e064036014210577f5c7de351bb0 100644
--- a/sys/net/gnrc/network_layer/ipv6/ext/rh/gnrc_ipv6_ext_rh.c
+++ b/sys/net/gnrc/network_layer/ipv6/ext/rh/gnrc_ipv6_ext_rh.c
@@ -18,6 +18,8 @@
 #include "net/ipv6/ext/rh.h"
 #include "net/gnrc.h"
 
+#include "net/gnrc/icmpv6/error.h"
+
 #ifdef MODULE_GNRC_RPL_SRH
 #include "net/gnrc/rpl/srh.h"
 #endif
@@ -35,7 +37,8 @@ static void _forward_pkt(gnrc_pktsnip_t *pkt, ipv6_hdr_t *hdr)
 
     if (--(hdr->hl) == 0) {
         DEBUG("ipv6_ext_rh: hop limit reached 0: drop packet\n");
-        gnrc_pktbuf_release(pkt);
+        gnrc_icmpv6_error_time_exc_send(ICMPV6_ERROR_TIME_EXC_HL, pkt);
+        gnrc_pktbuf_release_error(pkt, ETIMEDOUT);
         return;
     }
     /* remove L2 headers around IPV6 */
@@ -66,6 +69,7 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt)
     ipv6_ext_rh_t *ext = pkt->data;
     ipv6_hdr_t *hdr;
     int res = GNRC_IPV6_EXT_RH_AT_DST;
+    void *err_ptr = NULL;
 
     /* check seg_left early to avoid duplicating the packet */
     if (ext->seg_left == 0) {
@@ -77,11 +81,12 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt)
     switch (ext->type) {
 #ifdef MODULE_GNRC_RPL_SRH
         case IPV6_EXT_RH_TYPE_RPL_SRH:
-            res = gnrc_rpl_srh_process(hdr, (gnrc_rpl_srh_t *)ext);
+            res = gnrc_rpl_srh_process(hdr, (gnrc_rpl_srh_t *)ext, &err_ptr);
             break;
 #endif
         default:
             res = GNRC_IPV6_EXT_RH_ERROR;
+            err_ptr = &ext->type;
             break;
     }
     switch (res) {
@@ -91,7 +96,17 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt)
         case GNRC_IPV6_EXT_RH_AT_DST:
             break;
         default:
-            gnrc_pktbuf_release(pkt);
+#ifdef MODULE_GNRC_ICMPV6_ERROR
+            if (err_ptr) {
+                gnrc_icmpv6_error_param_prob_send(
+                        ICMPV6_ERROR_PARAM_PROB_HDR_FIELD,
+                        err_ptr, pkt
+                    );
+            }
+#else
+            (void)err_ptr;
+#endif
+            gnrc_pktbuf_release_error(pkt, EINVAL);
             break;
     }
     return res;
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 618d749a1a3ae106f863cbc869e76ace9db9c191..fdf72ccbe7e1b11c962d0d0a30d26d03c75686ed 100644
--- a/sys/net/gnrc/routing/rpl/srh/gnrc_rpl_srh.c
+++ b/sys/net/gnrc/routing/rpl/srh/gnrc_rpl_srh.c
@@ -31,10 +31,10 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN];
 
 /* 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)
+static void *_contains_multiple_of_my_addr(const ipv6_addr_t *dst,
+                                           const gnrc_rpl_srh_t *rh,
+                                           unsigned num_addr,
+                                           unsigned compri_addr_len)
 {
     ipv6_addr_t addr;
     uint8_t *addr_vec = (uint8_t *) (rh + 1);
@@ -45,30 +45,30 @@ static bool _contains_multiple_of_my_addr(const ipv6_addr_t *dst,
 
     memcpy(&addr, dst, pref_elided);
     for (unsigned i = 0; i < num_addr; i++) {
+        uint8_t *addr_vec_ptr = &addr_vec[i * compri_addr_len];
+
         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);
+        memcpy(&addr.u8[pref_elided], addr_vec_ptr, 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;
+                return addr_vec_ptr;
             }
             found_pos = i;
             found = true;
         }
     }
-    return false;
+    return NULL;
 }
 
-int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
+int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh, void **err_ptr)
 {
     ipv6_addr_t addr;
-    uint8_t *addr_vec = (uint8_t *) (rh + 1);
+    uint8_t *addr_vec = (uint8_t *) (rh + 1), *current_address;
     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;
@@ -83,7 +83,7 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
     if (rh->seg_left > num_addr) {
         DEBUG("RPL SRH: number of segments left > number of addresses - "
               "discard\n");
-        /* TODO ICMP Parameter Problem - Code 0 */
+        *err_ptr = &rh->seg_left;
         return GNRC_IPV6_EXT_RH_ERROR;
     }
 
@@ -94,24 +94,27 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
     compri_addr_len = sizeof(ipv6_addr_t) - GNRC_RPL_SRH_COMPRI(rh->compr);
     addr_len = sizeof(ipv6_addr_t) - pref_elided;
     memcpy(&addr, &ipv6->dst, pref_elided);
-    memcpy(&addr.u8[pref_elided],
-           &addr_vec[(current_pos - 1) * compri_addr_len],
-           addr_len);
+    current_address = &addr_vec[(current_pos - 1) * compri_addr_len];
+    memcpy(&addr.u8[pref_elided], current_address, addr_len);
 
-    if (ipv6_addr_is_multicast(&ipv6->dst) || ipv6_addr_is_multicast(&addr)) {
-        DEBUG("RPL SRH: found a multicast address - discard\n");
-        /* TODO discard the packet */
+    if (ipv6_addr_is_multicast(&ipv6->dst)) {
+        DEBUG("RPL SRH: found a multicast destination address - discard\n");
+        *err_ptr = &ipv6->dst;
+        return GNRC_IPV6_EXT_RH_ERROR;
+    }
+    if (ipv6_addr_is_multicast(&addr)) {
+        DEBUG("RPL SRH: found a multicast addres in next address - discard\n");
+        *err_ptr = current_address;
         return GNRC_IPV6_EXT_RH_ERROR;
     }
 
     /* check if multiple addresses of my interface exist */
-    if (_contains_multiple_of_my_addr(&ipv6->dst, rh, num_addr,
-                                      compri_addr_len)) {
+    if ((*err_ptr = _contains_multiple_of_my_addr(&ipv6->dst, rh, num_addr,
+                                                  compri_addr_len))) {
         return GNRC_IPV6_EXT_RH_ERROR;
     }
     rh->seg_left = new_seg_left;
-    memcpy(&addr_vec[(current_pos - 1) * compri_addr_len],
-           &ipv6->dst.u8[pref_elided], addr_len);
+    memcpy(current_address, &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)), current_pos);