/* * $Id: nemesis-ospf.c,v 1.1.1.1 2003/10/31 21:29:37 jnathan Exp $ * * THE NEMESIS PROJECT * Copyright (C) 1999, 2000 Mark Grimes * Copyright (C) 2001 - 2003 Jeff Nathan * * nemesis-ospf.c (OSPF Packet Injector) * */ #include "nemesis-ospf.h" #include "nemesis.h" #if defined(WIN32) #include #endif static ETHERhdr etherhdr; static IPhdr iphdr; static OSPFhdr ospfhdr; static OSPFHELLOhdr ospfhellohdr; static LSAhdr lsahdr; static LSRhdr lsrhdr; static LSUhdr lsuhdr; static ASLSAhdr aslsahdr; static RTRLSAhdr rtrlsahdr; static DBDhdr dbdhdr; static NETLSAhdr netlsahdr; static SUMLSAhdr sumlsahdr; static FileData pd, ipod; static int got_payload; static int got_mode; static char *payloadfile = NULL; /* payload file name */ static char *ipoptionsfile = NULL; /* IP options file name */ static char *device = NULL; /* Ethernet device */ #if defined(WIN32) char *ifacetmp; #endif static void ospf_cmdline(int, char **); static int ospf_exit(int); static void ospf_initdata(void); static void ospf_usage(char *); static void ospf_validatedata(void); static void ospf_verbose(void); void nemesis_ospf(int argc, char **argv) { const char *module = "OSPF Packet Injection"; fprintf(stderr, "Sorry, OSPF is currently non-functional.\n"); ospf_exit(1); nemesis_maketitle(title, module, version); if (argc > 1 && !strncmp(argv[1], "help", 4)) ospf_usage(argv[0]); if (nemesis_seedrand() < 0) fprintf(stderr, "ERROR: Unable to seed random number generator.\n"); ospf_initdata(); ospf_cmdline(argc, argv); ospf_validatedata(); ospf_verbose(); if (got_payload) { #if defined(WIN32) if (builddatafromfile(TCP_LINKBUFFSIZE, &pd, (const char *)payloadfile, (const u_int32_t)PAYLOADMODE) < 0) #else if (builddatafromfile(((got_link == 1) ? TCP_LINKBUFFSIZE : TCP_RAWBUFFSIZE), &pd, (const char *)payloadfile, (const u_int32_t)PAYLOADMODE) < 0) #endif ospf_exit(1); } if (got_ipoptions) { if (builddatafromfile(OPTIONSBUFFSIZE, &ipod, (const char *)ipoptionsfile, (const u_int32_t)OPTIONSMODE) < 0) ospf_exit(1); } if (buildospf(ðerhdr, &iphdr, &pd, &ipod, device) < 0) { puts("\nOSPF Injection Failure"); ospf_exit(1); } else { puts("\nOSPF Packet Injected"); ospf_exit(0); } } static void ospf_initdata(void) { /* defaults */ etherhdr.ether_type = ETHERTYPE_IP; /* Ethernet type IP */ memset(etherhdr.ether_shost, 0, 6); /* Ethernet source address */ memset(etherhdr.ether_dhost, 0xff, 6); /* Ethernet destination address */ memset(&iphdr.ip_src.s_addr, 0, 4); /* IP source address */ memset(&iphdr.ip_dst.s_addr, 0, 4); /* IP destination address */ iphdr.ip_tos = IPTOS_LOWDELAY; /* IP type of service */ iphdr.ip_id = (u_int16_t)libnet_get_prand(PRu16); /* IP ID */ iphdr.ip_off = 0; /* IP fragmentation offset */ iphdr.ip_ttl = 255; /* IP TTL */ pd.file_mem = NULL; pd.file_s = 0; ipod.file_mem = NULL; ipod.file_s = 0; return; } static void ospf_validatedata(void) { struct sockaddr_in sin; /* validation tests */ if (iphdr.ip_src.s_addr == 0) iphdr.ip_src.s_addr = (u_int32_t)libnet_get_prand(PRu32); if (iphdr.ip_dst.s_addr == 0) iphdr.ip_dst.s_addr = (u_int32_t)libnet_get_prand(PRu32); /* if the user has supplied a source hardware addess but not a device * try to select a device automatically */ if (memcmp(etherhdr.ether_shost, zero, 6) && !got_link && !device) { if (libnet_select_device(&sin, &device, (char *)&errbuf) < 0) { fprintf(stderr, "ERROR: Device not specified and unable to " "automatically select a device.\n"); ospf_exit(1); } else { #ifdef DEBUG printf("DEBUG: automatically selected device: " " %s\n", device); #endif got_link = 1; } } /* if a device was specified and the user has not specified a source * hardware address, try to determine the source address automatically */ if (got_link) { if ((nemesis_check_link(ðerhdr, device)) < 0) { fprintf(stderr, "ERROR: cannot retrieve hardware address of %s.\n", device); ospf_exit(1); } } if (got_mode > 1) { fprintf(stderr, "ERROR: OSPF injection mode multiply specified - " "select only one.\n"); ospf_exit(1); } } static void ospf_usage(char *arg) { nemesis_printtitle((const char *)title); printf("OSPF usage:\n %s [-v (verbose)] [options]\n\n", arg); printf("OSPF Packet Types: \n" " -p \n" " -pH HELLO, -pa LSA, -pD DBD, -pL LSR, -pU LSU\n"); printf("OSPF HELLO options: \n" " -N \n" " -i \n" " -l \n"); printf("OSPF DBD options: \n" " -z \n" " -x \n"); printf("OSPF LSU options: \n" " -B \n"); printf("OSPF LSA related options: \n" " -L \n" " -G \n"); printf("OSPF LSA_RTR options: \n" " -u \n" " -y \n" " -k \n"); printf("OSPF LSA_AS_EXT options: \n" " -f \n" " -g \n"); printf("OSPF options: \n" " -R \n" " -A \n" " -a \n" " -m \n" " -s \n" " -r \n" " -n \n" " -o \n" " -P \n\n"); printf("IP Options\n" " -S \n" " -D \n" " -I \n" " -t \n" " -T \n" " -F \n" " -F[D],[M],[R],[offset]\n" " -O \n\n"); printf("Data Link Options: \n" #if defined(WIN32) " -d \n" #else " -d \n" #endif " -H \n" " -M \n"); #if defined(WIN32) printf(" -Z (List available network interfaces by number)\n"); #endif putchar('\n'); ospf_exit(1); } static void ospf_cmdline(int argc, char **argv) { int opt, i; u_int32_t addr_tmp[6]; char *ospf_options; char cmd_mode = 0; extern char *optarg; extern int optind; #if defined(ENABLE_PCAPOUTPUT) #if defined(WIN32) ospf_options = "a:A:B:d:D:f:F:g:G:H:i:k:I:l:L:m:M:n:N:o:O:p:P:r:R:s:S:t:T:u:x:y:z:vWZ?"; #else ospf_options = "a:A:B:d:D:f:F:g:G:H:i:k:I:l:L:m:M:n:N:o:O:p:P:r:R:s:S:t:T:u:x:y:z:vW?"; #endif #else #if defined(WIN32) ospf_options = "a:A:B:d:D:f:F:g:G:H:i:k:I:l:L:m:M:n:N:o:O:p:P:r:R:s:S:t:T:u:x:y:z:vZ?"; #else ospf_options = "a:A:B:d:D:f:F:g:G:H:i:k:I:l:L:m:M:n:N:o:O:p:P:r:R:s:S:t:T:u:x:y:z:v?"; #endif #endif while ((opt = getopt(argc, argv, ospf_options)) != -1) { switch (opt) { case 'a': /* OSPF authorization type */ ospfhdr.ospf_auth_type = (u_int16_t)htons(xgetint16(optarg)); break; case 'A': /* OSPF area ID */ if ((nemesis_name_resolve(optarg, (u_int32_t *)&ospfhdr.ospf_area_id.s_addr)) < 0) { fprintf(stderr, "ERROR: Invalid OSPF area ID IP address: " "\"%s\".\n", optarg); ospf_exit(1); } break; case 'B': /* OSPF # of broadcasted link state advertisements */ lsuhdr.lsu_num = (u_int32_t)htonl(xgetint32(optarg)); break; case 'd': /* Ethernet device */ #if defined(WIN32) if (nemesis_getdev(atoi(optarg), &device) < 0) { fprintf(stderr, "ERROR: Unable to lookup device: '%d'.\n", atoi(optarg)); ospf_exit(1); } #else if (strlen(optarg) < 256) { device = strdup(optarg); got_link = 1; } else { fprintf(stderr, "ERROR: device %s > 256 characters.\n", optarg); ospf_exit(1); } #endif break; case 'D': /* destination IP address */ if ((nemesis_name_resolve(optarg, (u_int32_t *)&iphdr.ip_dst.s_addr)) < 0) { fprintf(stderr, "ERROR: Invalid destination IP address: " "\"%s\".\n", optarg); ospf_exit(1); } break; case 'f': /* external AS LSA forwarding IP address */ if ((nemesis_name_resolve(optarg, (u_int32_t *)&aslsahdr.as_fwd_addr.s_addr)) < 0) { fprintf(stderr, "ERROR: Invalid external LSA forwarding IP " "address: \"%s\".\n", optarg); ospf_exit(1); } break; case 'F': /* IP fragmentation options */ if (parsefragoptions(&iphdr, optarg) < 0) ospf_exit(1); break; case 'g': /* OSPF external route tag */ aslsahdr.as_rte_tag = (u_int32_t)htonl(xgetint32(optarg)); break; case 'G': /* OSPF link state acknowledgment age in seconds */ lsahdr.lsa_age = (u_int16_t)htons(xgetint16(optarg)); break; case 'H': /* Ethernet source address */ memset(addr_tmp, 0, sizeof(addr_tmp)); sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", &addr_tmp[0], &addr_tmp[1], &addr_tmp[2], &addr_tmp[3], &addr_tmp[4], &addr_tmp[5]); for (i = 0; i < 6; i++) etherhdr.ether_shost[i] = (u_int8_t)addr_tmp[i]; break; case 'i': /* OSPF HELLO link state countdown timer in seconds */ ospfhellohdr.hello_dead_intvl = (u_int16_t)htonl(xgetint32(optarg)); break; case 'I': /* IP ID */ iphdr.ip_id = xgetint16(optarg); break; case 'k': /* OSPF link state acknowledgment link data */ rtrlsahdr.rtr_link_data = (u_int32_t)htonl(xgetint32(optarg)); break; case 'l': /* OSPF HELLO las packet interval in seconds */ ospfhellohdr.hello_intrvl = (u_int16_t)htons(xgetint16(optarg)); break; case 'L': /* OSPF link state request ID */ lsrhdr.lsr_lsid = (u_int32_t)htonl(xgetint32(optarg)); break; case 'm': /* OSPF link state acknowledgment link metric */ rtrlsahdr.rtr_metric = (u_int16_t)htons(xgetint16(optarg)); break; case 'M': /* Ethernet destination address */ memset(addr_tmp, 0, sizeof(addr_tmp)); sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", &addr_tmp[0], &addr_tmp[1], &addr_tmp[2], &addr_tmp[3], &addr_tmp[4], &addr_tmp[5]); for (i = 0; i < 6; i++) etherhdr.ether_dhost[i] = (u_int8_t)addr_tmp[i]; break; case 'n': /* OSPF multi-purpose netmask placement */ if ((nemesis_name_resolve(optarg, (u_int32_t *)&ospfhellohdr.hello_nmask.s_addr)) < 0) { fprintf(stderr, "ERROR: Invalid netmask IP address: \"%s\"" ".\n", optarg); ospf_exit(1); } else { memcpy(&ospfhellohdr.hello_nmask.s_addr, &netlsahdr.net_nmask.s_addr, sizeof(u_int)); memcpy(&ospfhellohdr.hello_nmask.s_addr, &sumlsahdr.sum_nmask.s_addr, sizeof(u_int)); memcpy(&ospfhellohdr.hello_nmask.s_addr, &aslsahdr.as_nmask.s_addr, sizeof(u_int)); } break; case 'N': /* OSPF HELLO neighbor router */ if ((nemesis_name_resolve(optarg, (u_int32_t *)&ospfhellohdr.hello_nbr.s_addr)) < 0) { fprintf(stderr, "ERROR: Invalid OSPF HELLO neighbor " "IP address: \"%s\".\n", optarg); ospf_exit(1); } break; case 'o': /* OSPF multi purpose options */ ospfhellohdr.hello_opts = xgetint8(optarg); lsahdr.lsa_opts = xgetint8(optarg); dbdhdr.dbd_opts = xgetint8(optarg); break; case 'O': /* IP options file */ if (strlen(optarg) < 256) { ipoptionsfile = strdup(optarg); got_ipoptions = 1; } else { fprintf(stderr, "ERROR: IP options file %s > 256 " "characters.\n", optarg); ospf_exit(1); } break; case 'p': /* OSPF injection mode */ if (strlen(optarg) == 1) { cmd_mode = *optarg; } else { fprintf(stderr, "ERROR: Invalide OSPF injection mode: " "%s.\n", optarg); ospf_exit(1); } switch (cmd_mode) { case 'A': /* OSPF link state advertisement */ ospfhdr.ospf_type = LIBNET_OSPF_LSA; got_mode++; break; case 'D': /* OSPF database description */ ospfhdr.ospf_type = LIBNET_OSPF_DBD; got_mode++; break; case 'H': /* OSPF Hello */ ospfhdr.ospf_type = LIBNET_OSPF_HELLO; got_mode++; break; case 'L': /* OSPF link state request */ ospfhdr.ospf_type = LIBNET_OSPF_LSR; got_mode++; break; case 'U': /* OSPF link state update */ ospfhdr.ospf_type = LIBNET_OSPF_LSU; got_mode++; break; case '?': /* FALLTHROUGH */ default: fprintf(stderr, "ERROR: Invalid OSPF injection " "mode: %c.\n", cmd_mode); ospf_exit(1); /* NOTREACHED */ break; } break; case 'P': /* payload file */ if (strlen(optarg) < 256) { payloadfile = strdup(optarg); got_payload = 1; } else { fprintf(stderr, "ERROR: payload file %s > 256 " "characters.\n", payloadfile); ospf_exit(1); } break; case 'r': /* OSPF advertising router ID */ if ((nemesis_name_resolve(optarg, (u_int32_t *)&lsahdr.lsa_adv.s_addr)) < 0) { fprintf(stderr, "ERROR: Invalid OSPF advertising router ID " "(IP address): \"%s\".\n", optarg); ospf_exit(1); } break; case 'R': /* OSPF source router ID */ if ((nemesis_name_resolve(optarg, (u_int32_t *)&ospfhdr.ospf_rtr_id.s_addr)) < 0) { fprintf(stderr, "ERROR: Invalid OSPF source router ID (IP " "address): \"%s\".\n", optarg); ospf_exit(1); } break; case 's': /* OSPF DBD sequence number */ dbdhdr.dbd_seq = (u_int32_t)htonl(xgetint32(optarg)); break; case 'S': /* source IP address */ if ((nemesis_name_resolve(optarg, (u_int32_t *)&iphdr.ip_src.s_addr)) < 0) { fprintf(stderr, "ERROR: Invalid source IP address: \"%s\"." "\n", optarg); ospf_exit(1); } break; case 't': /* IP type of service */ iphdr.ip_tos = xgetint8(optarg); break; case 'T': /* IP time to live */ iphdr.ip_ttl = xgetint8(optarg); break; case 'u': /* OSPF number of links in link state header */ rtrlsahdr.rtr_num = (u_int16_t)htons(xgetint16(optarg)); break; case 'v': verbose++; if (verbose == 1) nemesis_printtitle((const char *)title); break; case 'x': /* OSPF DBD exchange type */ dbdhdr.dbd_type = xgetint8(optarg); break; case 'y': /* OSPF description of router link */ rtrlsahdr.rtr_type = xgetint8(optarg); break; case 'z': /* OSPF DBD interface MTU size */ dbdhdr.dbd_mtu_len = (u_int16_t)htons(xgetint16(optarg)); break; case '?': /* FALLTHROUGH */ default: ospf_usage(argv[0]); break; } } argc -= optind; argv += optind; return; } static int ospf_exit(int code) { if (got_payload) free(pd.file_mem); if (got_ipoptions) free(ipod.file_mem); if (device != NULL) free(device); if (ipoptionsfile != NULL) free(ipoptionsfile); if (payloadfile != NULL) free(payloadfile); #if defined(WIN32) if (ifacetmp != NULL) free(ifacetmp); #endif exit(code); } static void ospf_verbose(void) { if (verbose) { if (got_link) nemesis_printeth(ðerhdr); nemesis_printip(&iphdr); nemesis_printospf(&ospfhdr); printf("[OSPF Options] 0x%x\n", ooptions); printf("[Priority] %d\n", priority); printf("[Advertising Router ID] 0x%ld\n", addrid); printf("[Advertising Area ID] 0x%ld\n", addaid); if (mode == 1) { printf("[Dead router interval] %d\n", dead_int); } else if (mode == 2) { printf("[Netmask] %ld\n", mask); printf("[Sequence Number] %d\n", seqnum); printf("[Router Advertisement Age] %d\n", ospf_age); printf("[Link State ID] %d\n", rtrid); } else if (mode == 3) { printf("[Link State ID] %d\n", rtrid); } } return; }