/* Send an ICMP packet, such as host unreachable, to the source and destination addresses */ void rst_icmp_send(pkt_t *rst) { struct ip *ih = NULL; struct tcphdr *th = NULL; int pair = 0; char *state = NULL; size_t icmp_len = 0; ih = (struct ip *)(rst->pkt + sizeof(struct ether_header)); th = (struct tcphdr *)(rst->pkt + sizeof(struct ether_header) + sizeof(struct ip)); /* The interface described in "Building Open Source Network Security Tools" * appears to be deprecated. The new interface tunnels an IPv4 packet * within the ICMP unreachable using the libnet context. */ switch (rst->icmp.type) { /* RFC 792 * * Type 3 * * Codes 0, 1, 4, and 5 may be received from a gateway. Codes 2 and * 3 may be received from a host. * * 0 = net unreachable; * 1 = host unreachable; * 2 = protocol unreachable; * 3 = port unreachable; * 4 = fragmentation needed and DF set; * 5 = source route failed. * */ case ICMP_UNREACH: icmp_len = LIBNET_ICMPV4_UNREACH_H + LIBNET_IPV4_H + ICMP_PKTLEN; LIBNET_ERR(libnet_build_icmpv4_unreach( rst->icmp.type, /* ICMP type, e.g. 3 (Unreachable) */ rst->icmp.code, /* ICMP code, e.g., 1 (Bad Host) */ 0, /* auto checksum */ (u_char *)ih, /* payload */ LIBNET_IPV4_H + ICMP_PKTLEN, /* payload size */ rst->l, /* libnet context */ 0 /* ptag */ )); break; /* * Type 5 * * Codes 0, 1, 2, and 3 may be received from a gateway. * * 0 = Redirect datagrams for the Network. * 1 = Redirect datagrams for the Host. * 2 = Redirect datagrams for the Type of Service and Network. * 3 = Redirect datagrams for the Type of Service and Host. * */ case ICMP_REDIRECT: icmp_len = LIBNET_ICMPV4_REDIRECT_H; LIBNET_ERR(libnet_build_icmpv4_unreach( rst->icmp.type, rst->icmp.code, 0, (u_char *)ih, LIBNET_IPV4_H + ICMP_PKTLEN, rst->l, 0)); break; /* * Type 11 * * Code 0 may be received from a gateway. Code 1 may be received * from a host. * * 0 = time to live exceeded in transit * 1 = fragment reassembly time exceeded * */ case ICMP_TIMXCEED: icmp_len = LIBNET_ICMPV4_TIMXCEED_H + LIBNET_IPV4_H + ICMP_PKTLEN; LIBNET_ERR(libnet_build_icmpv4_timeexceed( rst->icmp.type, rst->icmp.code, 0, (u_char *)ih, LIBNET_IPV4_H + ICMP_PKTLEN, rst->l, 0)); break; case ICMP_PARAMPROB: case ICMP_SOURCEQUENCH: errx(EXIT_FAILURE, "Not supported by libnet."); break; default: errx(EXIT_FAILURE, "ICMP type %d is not supported yet\n", rst->icmp.type); } LIBNET_ERR(libnet_build_ipv4( LIBNET_IPV4_H + icmp_len, /* payload size */ IPTOS_LOWDELAY | IPTOS_THROUGHPUT, /* TOS */ ntohs(ih->ip_id)+1, /* IP ID */ 0, /* Frag */ 64, /* TTL */ IPPROTO_ICMP, /* Protocol */ 0, /* auto checksum */ ih->ip_dst.s_addr, /* source */ ih->ip_src.s_addr, /* destination */ NULL, /* payload */ 0, /* payload size */ rst->l, /* libnet context */ 0 /* libnet ptag */ )); state = ((libnet_write(rst->l) == -1) ? "x" : "I"); (void)fprintf(stdout, "[%s] SRC = %15s:%-6u DST = %15s:%-6u len = %d/%d\n", state, libnet_addr2name4(PAIR(pair, ih->ip_src.s_addr, ih->ip_dst.s_addr), LIBNET_DONT_RESOLVE), PAIR(pair, ntohs(th->th_sport), ntohs(th->th_dport)), libnet_addr2name4(PAIR(pair, ih->ip_dst.s_addr, ih->ip_src.s_addr), LIBNET_DONT_RESOLVE), PAIR(pair, ntohs(th->th_dport), ntohs(th->th_sport)), LIBNET_IPV4_H + (u_int32_t)icmp_len, ntohs(ih->ip_len)); (void)fflush(stdout); usleep(rst->sleep_for); }
int main(int argc, char **argv) { int c; libnet_t *l; libnet_ptag_t t; u_long src_ip, dst_ip; u_char payload[8] = {0x00, 0x36, 0xff, 0xff, 0x00, 0x21, 0x00, 0x00}; u_long payload_s = 8; char errbuf[LIBNET_ERRBUF_SIZE]; printf("libnet 1.1 packet shaping: ICMP unreachable[link]\n"); /* * Initialize the library. Root priviledges are required. */ l = libnet_init( LIBNET_LINK, /* injection type */ NULL, /* network interface */ errbuf); /* errbuf */ if (l == NULL) { fprintf(stderr, "libnet_init() failed: %s", errbuf); exit(EXIT_FAILURE); } src_ip = 0; dst_ip = 0; while((c = getopt(argc, argv, "d:s:")) != EOF) { switch (c) { case 'd': if ((dst_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1) { fprintf(stderr, "Bad destination IP address: %s\n", optarg); exit(1); } break; case 's': if ((src_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1) { fprintf(stderr, "Bad source IP address: %s\n", optarg); exit(1); } break; } } if (!src_ip || !dst_ip) { usage(argv[0]); exit(EXIT_FAILURE); } t = libnet_build_icmpv4_unreach( ICMP_UNREACH, /* type */ ICMP_UNREACH_PORT, /* code */ 0, /* checksum */ LIBNET_IPV4_H + LIBNET_UDP_H, /* o length */ IPTOS_LOWDELAY | IPTOS_THROUGHPUT, /* o IP tos */ 0xff, /* o IP ID */ 0, /* o frag */ 64, /* o TTL */ IPPROTO_UDP, /* o protocol */ 0x7012, /* o checksum */ dst_ip, /* o source IP */ src_ip, /* o destination IP */ payload, /* payload */ payload_s, /* payload size */ l, /* libnet handle */ 0); if (t == -1) { fprintf(stderr, "Can't build ICMP header: %s\n", libnet_geterror(l)); goto bad; } t = libnet_build_ipv4( LIBNET_IPV4_H + LIBNET_ICMPV4_UNREACH_H + LIBNET_IPV4_H, /* length */ IPTOS_LOWDELAY | IPTOS_THROUGHPUT, /* TOS */ 0xee, /* IP ID */ 0, /* IP Frag */ 64, /* TTL */ IPPROTO_ICMP, /* protocol */ 0, /* checksum */ src_ip, /* source IP */ dst_ip, /* destination IP */ NULL, /* payload */ 0, /* payload size */ l, /* libnet handle */ 0); if (t == -1) { fprintf(stderr, "Can't build IP header: %s\n", libnet_geterror(l)); goto bad; } t = libnet_build_ethernet( enet_dst, /* ethernet destination */ enet_src, /* ethernet source */ ETHERTYPE_IP, /* protocol type */ NULL, /* payload */ 0, /* payload size */ l, /* libnet handle */ 0); /* libnet id */ if (t == -1) { fprintf(stderr, "Can't build ethernet header: %s\n", libnet_geterror(l)); goto bad; } /* * Write it to the wire. */ c = libnet_write(l); if (c == -1) { fprintf(stderr, "Write error: %s\n", libnet_geterror(l)); goto bad; } else { fprintf(stderr, "Wrote %d byte ICMP packet; check the wire.\n", c); } libnet_destroy(l); return (EXIT_SUCCESS); bad: libnet_destroy(l); return (EXIT_FAILURE); }