Here’s how Linux kernel 3.1.2 handles ICMP Redirect message.

First, the kernel checks the handler table and invoke icmp_redirect as the corresponding handler of ICMP Redirect packet.

// net/ipv4/icmp.c
974 static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
994     [ICMP_REDIRECT] = {
995         .handler = icmp_redirect,
// net/ipv4/icmp.c
765 static void icmp_redirect(struct sk_buff *skb)
775     icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway);
// net/ipv4/icmp.c
645 static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
662     ipprot->err_handler(skb, info);

In net/ipv4/af_inet.c we figure out the error handler of ICMP is icmp_err

// net/ipv4/af_inet.c
1555 static const struct net_protocol icmp_protocol = {
1557     .err_handler =  icmp_err,
1560 };
// net/ipv4/icmp.c
947 void icmp_err(struct sk_buff *skb, u32 info)
967     else if (type == ICMP_REDIRECT)
968         ipv4_redirect(skb, net, 0, 0, IPPROTO_ICMP, 0);
// net/ipv4/route.c
1078 void ipv4_redirect(struct sk_buff *skb, struct net *net,
1079                    int oif, u32 mark, u8 protocol, int flow_flags)
1089     __ip_do_redirect(rt, skb, &fl4, false);

Here’s the function that ICMP Redirect is actually processed.

// net/ipv4/route.c
706 static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb,
707                              struct flowi4 *fl4, bool kill_route)
756     if (fib_lookup(net, fl4, &res) == 0) {
757         struct fib_nh *nh = &FIB_RES_NH(res);
759         update_or_create_fnhe(nh, fl4->daddr, new_gw, 0, 0);
761 }

update_or_create_fnhe takes care the rest of route update procedure.