/****************************************************************************** * Copyright (c) 2004 Rodney Caudle * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * Application : sendstuff * Filename : sendstuff.c * Sendstuff.c handles the crafting and sending of three * fragmented packets: the first one is labeled as ICMP, the second as * UDP and the third as ICMP. * * Updated: * 01-30-2004 - initial creation ******************************************************************************/ #include #include #include #include #include #define NETDEV "lo" /* network device; obtained using netstat -r */ #define BUFLEN 1500 /* max length of packet data ( if you change this you'll have to recalculate the offsets again since I don't have a clean way way to calculate the offsets of fragments yet ) */ #define ADDRLEN 100 /* max length of an address */ #define FUNTTL 0x69 /* fun for a default TTL */ //#define DEBUG 0 /* do NOT include the debug information */ #define DEBUG 1 /* include the debug information */ #define __DEBUG__ /* global variables */ int pktcount = 0; /* function definitions */ unsigned short csum (unsigned short *buf, int nwords); int sendpacket(int sd, char *datagram, u_short length, struct sockaddr *sin); /* The Beginning of the end */ int main(int argc, char *argv[]) { char *dev = NETDEV; int i, sd; char datagram1[BUFLEN], datagram2[BUFLEN], datagram3[BUFLEN]; struct sockaddr sin2; int on = 1; char srcaddr[ADDRLEN], dstaddr[ADDRLEN]; memset(srcaddr,0,ADDRLEN); memset(dstaddr,0,ADDRLEN); /* Double check for valid numbers of parameters: two or none */ if (argc != 4) { fprintf(stderr, "Error: Invalid number of parameters passed. [%d] passed.\n\n", argc); fprintf(stderr, "Usage: sendstuff \n"); fprintf(stderr, " # sendstuff lo 127.0.0.1 127.0.0.1\n"); exit(1); } else { dev = argv[1]; if (strlen(srcaddr) <= strlen(argv[2])) { strncpy(srcaddr,argv[2],ADDRLEN); } else { strncpy(srcaddr,argv[2],strlen(argv[2])); } if (strlen(dstaddr) <= strlen(argv[3])) { strncpy(dstaddr,argv[3],ADDRLEN); } else { strncpy(dstaddr,argv[3],strlen(argv[3])); } if (DEBUG) fprintf(stderr, "source %d:%s [%d:%s] <=> dest %d:%s [%d:%s]\n", strlen(srcaddr),srcaddr,strlen(argv[2]),argv[2], strlen(dstaddr),dstaddr,strlen(argv[3]),argv[3]); } /* Define sin2 */ sin2.sa_family = AF_INET; strncpy(sin2.sa_data, dev, sizeof(sin2.sa_data)); /* Build definitions for the first packet... ICMP/IP */ struct ip *ippkt1 = (struct ip *)datagram1; struct icmphdr *icmppkt1 = (struct icmphdr *) (datagram1 + sizeof(struct ip)); /* Build definitions for the second packet... IP information only */ struct ip *ippkt2 = (struct ip *)datagram2; /* Build definitions for the third packet... IP information only */ struct ip *ippkt3 = (struct ip *)datagram3; /* Clear all the datagram structures to zeros */ memset(datagram1,0x00,BUFLEN); memset(datagram2,0x87,BUFLEN); memset(datagram3,0xff,BUFLEN); /* Before we get started... setup signal handlers */ signal(SIGHUP, SIG_IGN); /* Start talking... opening the device for writing */ fprintf(stderr, "Opening Device [%s] for crafting 3 packets from %s to %s.\n", dev,srcaddr,dstaddr); /* * Create a socket of the kind that can write whatever packet you want. The type of socket is * set to SOCK_DGRAM so we don't have to worry about the Link Layer data. If you would like to * "doctor" the Link Layer data as well, change the type to SOCK_RAW... but you'll have to use the * raw_* structures instead. Make sure to change the code appropriately. */ if ((sd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("Cannot create an ETH_P_ALL socket. This is usually restricted to root privileges only."); exit(1); } /* Build First Packet IP Information */ ippkt1->ip_hl = 5; /* don't need to flip */ ippkt1->ip_v = 4; /* don't need to flip */ ippkt1->ip_tos = 0; /* don't need to flip */ ippkt1->ip_len = BUFLEN; /* don't need to flip */ ippkt1->ip_id = htons (54321); /* need to flip */ ippkt1->ip_off |= htons(IP_MF); /* need to flip */ ippkt1->ip_ttl = FUNTTL; /* don't need to flip */ ippkt1->ip_p = IPPROTO_ICMP; /* don't need to flip */ ippkt1->ip_sum = 0; /* don't need to flip */ ippkt1->ip_dst.s_addr = inet_addr(dstaddr); /* don't need to flip */ ippkt1->ip_src.s_addr = inet_addr(srcaddr); /* don't need to flip */ /* Build First Packet ICMP Information */ icmppkt1->type = ICMP_ECHO; icmppkt1->code = 0; icmppkt1->checksum =0; icmppkt1->un.echo.id = htonl(54321); icmppkt1->un.echo.sequence = htonl(54321); /* Calculate Checksums */ icmppkt1->checksum = csum ((unsigned short *) icmppkt1, 8); ippkt1->ip_sum = csum ((unsigned short *) datagram1, ippkt1->ip_len); /* Packet #1 Ready */ if (DEBUG) fprintf(stderr, " >>Packet #1 ready to send.\n"); /* Build Second Packet IP Information */ ippkt2->ip_hl = 5; ippkt2->ip_v = 4; ippkt2->ip_tos = 0; ippkt2->ip_len = BUFLEN; ippkt2->ip_id = htons (54321); ippkt2->ip_off = 0xb900; ippkt2->ip_off |= htons(IP_MF); ippkt2->ip_ttl = FUNTTL; ippkt2->ip_p = IPPROTO_UDP; ippkt2->ip_sum = 0; ippkt2->ip_dst.s_addr = inet_addr(dstaddr); ippkt2->ip_src.s_addr = inet_addr(srcaddr); /* Calculate Checksums */ ippkt2->ip_sum = csum ((unsigned short *) datagram2, ippkt2->ip_len >> 1); /* Packet #2 Ready */ if (DEBUG) fprintf(stderr, " >>Packet #2 ready to send.\n"); /* Build Third Packet IP Information */ ippkt3->ip_hl = 5; ippkt3->ip_v = 4; ippkt3->ip_tos = 0; ippkt3->ip_len = BUFLEN; ippkt3->ip_id = htons (54321); ippkt3->ip_off = 0x7201; ippkt3->ip_ttl = FUNTTL; ippkt3->ip_p = IPPROTO_ICMP; ippkt3->ip_sum = 0; ippkt3->ip_dst.s_addr = inet_addr(dstaddr); ippkt3->ip_src.s_addr = inet_addr(srcaddr); /* Calculate Checksums */ ippkt3->ip_sum = csum ((unsigned short *) datagram3, ippkt3->ip_len >> 1); /* Packet #3 Ready */ if (DEBUG) fprintf(stderr, " >>Packet #3 ready to send.\n"); /* send the packets */ sendpacket(sd, datagram1, ippkt1->ip_len, &sin2); #ifdef __DEBUG__ fprintf(stderr, " >>Packet #1 sent.\n"); #endif sendpacket(sd, datagram2, ippkt2->ip_len, &sin2); if (DEBUG) fprintf(stderr, " >>Packet #2 sent.\n"); sendpacket(sd, datagram3, ippkt3->ip_len, &sin2); if (DEBUG) fprintf(stderr, " >>Packet #3 sent.\n"); /* Close and Exit */ close(sd); return(0); } unsigned short csum (unsigned 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; } int sendpacket(int sd, char *datagram, u_short length, struct sockaddr *sin) { if (!sendto(sd, datagram, length,0, sin, sizeof(struct sockaddr))) { fprintf(stderr, "Error: packet did not send [%d].\n", length); return(-1); } else { pktcount++; if (DEBUG) { fprintf(stderr, " >>Packet %d sent, %d bytes sent.\n", pktcount, length); fprintf(stderr, " --> [0x%.2x,0x%.2x] [0x%.2x|0x%.2x]. <--\n", datagram[6], datagram[7], datagram[20], datagram[21]); } } return(0); }