u_int32_t libnet_get_ipaddr4(libnet_t *l) { struct ifreq ifr; register struct sockaddr_in *sin; int fd; if (l == NULL) { return (-1); } /* create dummy socket to perform an ioctl upon */ fd = socket(PF_INET, SOCK_DGRAM, 0); if (fd == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): socket(): %s\n", __func__, strerror(errno)); return (-1); } sin = (struct sockaddr_in *)&ifr.ifr_addr; if (l->device == NULL) { if (libnet_select_device(l) == -1) { /* error msg set in libnet_select_device() */ close(fd); return (-1); } } strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) -1); ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; ifr.ifr_addr.sa_family = AF_INET; if (ioctl(fd, SIOCGIFADDR, (int8_t*) &ifr) < 0) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): ioctl(): %s\n", __func__, strerror(errno)); close(fd); return (-1); } close(fd); return (sin->sin_addr.s_addr); }
static void ip_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) { printf("ERROR: Device not specified and unable to automatically " "select a device.\n"); ip_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); ip_exit(1); } } return; }
struct libnet_ether_addr * libnet_get_hwaddr(libnet_t *l) { int mib[6]; size_t len; int8_t *buf, *next, *end; struct if_msghdr *ifm; struct sockaddr_dl *sdl; /* This implementation is not-reentrant. */ static struct libnet_ether_addr ea; mib[0] = CTL_NET; mib[1] = AF_ROUTE; mib[2] = 0; mib[3] = AF_LINK; mib[4] = NET_RT_IFLIST; mib[5] = 0; if (l == NULL) { return (NULL); } if (l->device == NULL) { if (libnet_select_device(l) == -1) { /* err msg set in libnet_select_device */ return (NULL); } } if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s", __func__, strerror(errno)); return (NULL); } buf = (int8_t *)malloc(len); if (buf == NULL) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s", __func__, strerror(errno)); return (NULL); } if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s", __func__, strerror(errno)); free(buf); return (NULL); } end = buf + len; for (next = buf ; next < end ; next += ifm->ifm_msglen) { ifm = (struct if_msghdr *)next; if (ifm->ifm_version != RTM_VERSION) continue; if (ifm->ifm_type == RTM_IFINFO) { sdl = (struct sockaddr_dl *)(ifm + 1); if (sdl->sdl_type != IFT_ETHER && sdl->sdl_type != IFT_FASTETHER && sdl->sdl_type != IFT_FASTETHERFX && sdl->sdl_type != IFT_GIGABITETHERNET && sdl->sdl_type != IFT_L2VLAN) continue; if (strncmp(&sdl->sdl_data[0], l->device, sdl->sdl_nlen) == 0) { memcpy(ea.ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN); break; } } } free(buf); if (next == end) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): interface %s of known type not found.", __func__, l->device); return NULL; } return (&ea); }
libnet_t * libnet_init(int injection_type, const char *device, char *err_buf) { libnet_t *l = NULL; #if !defined(__WIN32__) if (getuid() && geteuid()) { snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): UID or EUID of 0 required\n", __func__); goto bad; } #else WSADATA wsaData; if ((WSAStartup(0x0202, &wsaData)) != 0) { snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): unable to initialize winsock 2\n", __func__); goto bad; } #endif l = (libnet_t *)malloc(sizeof (libnet_t)); if (l == NULL) { snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n", __func__, strerror(errno)); goto bad; } memset(l, 0, sizeof (*l)); l->injection_type = injection_type; l->ptag_state = LIBNET_PTAG_INITIALIZER; l->device = (device ? strdup(device) : NULL); strncpy(l->label, LIBNET_LABEL_DEFAULT, LIBNET_LABEL_SIZE); l->label[sizeof(l->label)] = '\0'; switch (l->injection_type) { case LIBNET_LINK: case LIBNET_LINK_ADV: if (libnet_select_device(l) == -1) { snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s", l->err_buf); goto bad; } if (libnet_open_link(l) == -1) { snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s", l->err_buf); goto bad; } break; case LIBNET_RAW4: case LIBNET_RAW4_ADV: if (libnet_open_raw4(l) == -1) { snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s", l->err_buf); goto bad; } break; case LIBNET_RAW6: case LIBNET_RAW6_ADV: if (libnet_open_raw6(l) == -1) { snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s", l->err_buf); goto bad; } break; default: snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): unsupported injection type\n", __func__); goto bad; break; } return (l); bad: if (l) { libnet_destroy(l); } return (NULL); }
int main(int argc, char *argv[]) { int packet_size, /* size of our packet */ payload_size, /* size of our packet */ c; /* misc */ u_long src_ip, dst_ip; /* source ip, dest ip */ u_short bport, eport; /* beginning and end ports */ u_short cport; /* current port */ u_char payload[MAX_PAYLOAD_SIZE]; /* packet payload */ u_char *packet; /* pointer to our packet buffer */ char err_buf[LIBNET_ERRBUF_SIZE]; /* error buffer */ u_char *device; /* pointer to the device to use */ struct libnet_link_int *network; /* pointer to link interface struct */ struct libnet_plist_chain plist; /* plist chain */ struct libnet_plist_chain *plist_p; /* plist chain pointer */ printf("libnet example code:\tmodule 4\n\n"); printf("packet injection interface:\tlink layer\n"); printf("packet type:\t\t\tUDP [with payload] using port list chaining\n"); plist_p = NULL; device = NULL; src_ip = 0; dst_ip = 0; while ((c = getopt(argc, argv, "i:d:s:p:")) != EOF) { switch (c) { case 'd': if (!(dst_ip = libnet_name_resolve(optarg, LIBNET_RESOLVE))) { libnet_error(LIBNET_ERR_FATAL, "Bad destination IP address: %s\n", optarg); } break; case 'i': device = optarg; break; case 's': if (!(src_ip = libnet_name_resolve(optarg, LIBNET_RESOLVE))) { libnet_error(LIBNET_ERR_FATAL, "Bad source IP address: %s\n", optarg); } break; case 'p': plist_p = &plist; if (libnet_plist_chain_new(&plist_p, optarg) == -1) { libnet_error(LIBNET_ERR_FATAL, "Could not build port list\n"); } break; default: usage(argv[0]); exit(EXIT_FAILURE); } } if (!src_ip || !dst_ip || !plist_p) { usage(argv[0]); exit(EXIT_FAILURE); } c = argc - optind; if (c != 1) { usage(argv[0]); exit(EXIT_FAILURE); } memset(payload, 0, sizeof(payload)); strncpy(payload, argv[optind], strlen(argv[optind])); /* * Step 1: Network Initialization (interchangable with step 2). */ if (device == NULL) { struct sockaddr_in sin; /* * Try to locate a device. */ if (libnet_select_device(&sin, &device, err_buf) == -1) { libnet_error(LIBNET_ERR_FATAL, "libnet_select_device failed: %s\n", err_buf); } printf("device:\t\t\t\t%s\n", device); } if ((network = libnet_open_link_interface(device, err_buf)) == NULL) { libnet_error(LIBNET_ERR_FATAL, "libnet_open_link_interface: %s\n", err_buf); } /* * Get the payload from the user. Hrm. This might fail on a Sparc * if byte alignment is off... */ payload_size = strlen(payload); /* * We're going to build a UDP packet with a payload using the * link-layer API, so this time we need memory for a ethernet header * as well as memory for the ICMP and IP headers and our payload. */ packet_size = LIBNET_IP_H + LIBNET_ETH_H + LIBNET_UDP_H + payload_size; /* * Step 2: Memory Initialization (interchangable with step 1). */ if (libnet_init_packet(packet_size, &packet) == -1) { libnet_error(LIBNET_ERR_FATAL, "libnet_init_packet failed\n"); } /* * Step 3: Packet construction (ethernet header). */ libnet_build_ethernet(enet_dst, enet_src, ETHERTYPE_IP, NULL, 0, packet); /* * Step 3: Packet construction (IP header). */ libnet_build_ip(LIBNET_UDP_H + payload_size, 0, /* IP tos */ 242, /* IP ID */ 0, /* Frag */ 64, /* TTL */ IPPROTO_UDP, /* Transport protocol */ src_ip, /* Source IP */ dst_ip, /* Destination IP */ NULL, /* Pointer to payload (none) */ 0, packet + LIBNET_ETH_H); /* Packet header memory */ while (libnet_plist_chain_next_pair(plist_p, &bport, &eport)) { while (!(bport > eport) && bport != 0) { cport = bport++; /* * Step 3: Packet construction (UDP header). */ libnet_build_udp(242, /* source port */ cport, /* dest. port */ payload, /* payload */ payload_size, /* payload length */ packet + LIBNET_ETH_H + LIBNET_IP_H); /* * Step 4: Packet checksums (ICMP header *AND* IP header). */ if (libnet_do_checksum(packet + ETH_H, IPPROTO_UDP, LIBNET_UDP_H + payload_size) == -1) { libnet_error(LIBNET_ERR_FATAL, "libnet_do_checksum failed\n"); } if (libnet_do_checksum(packet + ETH_H, IPPROTO_IP, LIBNET_IP_H) == -1) { libnet_error(LIBNET_ERR_FATAL, "libnet_do_checksum failed\n"); } /* * Step 5: Packet injection. */ c = libnet_write_link_layer(network, device, packet, packet_size); if (c < packet_size) { libnet_error(LN_ERR_WARNING, "libnet_write_link_layer only wrote %d bytes\n", c); } else { printf("construction and injection completed, wrote all %d bytes, port %d\n", c, cport); } } } /* * Shut down the interface. */ if (libnet_close_link_interface(network) == -1) { libnet_error(LN_ERR_WARNING, "libnet_close_link_interface couldn't close the interface"); } /* * Free packet memory. */ libnet_destroy_packet(&packet); return (c == -1 ? EXIT_FAILURE : EXIT_SUCCESS); }
struct libnet_ether_addr * libnet_get_hwaddr(libnet_t *l) { int mib[6]; size_t len; int8_t *buf, *next, *end; struct if_msghdr *ifm; struct sockaddr_dl *sdl; struct libnet_ether_addr *ea = NULL; mib[0] = CTL_NET; mib[1] = AF_ROUTE; mib[2] = 0; mib[3] = AF_LINK; mib[4] = NET_RT_IFLIST; mib[5] = 0; if (l == NULL) { return (NULL); } if (l->device == NULL) { if (libnet_select_device(l) == -1) { /* err msg set in libnet_select_device */ return (NULL); } } if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s\n", __func__, strerror(errno)); return (NULL); } buf = (int8_t *)malloc(len); if (buf == NULL) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n", __func__, strerror(errno)); return (NULL); } if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s\n", __func__, strerror(errno)); free(buf); return (NULL); } end = buf + len; for (next = buf ; next < end ; next += ifm->ifm_msglen) { ifm = (struct if_msghdr *)next; if (ifm->ifm_type == RTM_IFINFO) { sdl = (struct sockaddr_dl *)(ifm + 1); if (strncmp(&sdl->sdl_data[0], l->device, sdl->sdl_nlen) == 0) { if (!(ea = malloc(sizeof(struct libnet_ether_addr)))) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s", __func__, strerror(errno)); free(buf); return (NULL); } memcpy(ea->ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN); break; } } } free(buf); return (ea); }
/* * injection_write_ip * * Description: * - Write an IP packet into the wire. It can use either raw sockets * or the wire * * Inputs: * - ip_packet: the IP packet * * Outputs: * - return: 0 if ok, <0 if there were problems * */ int injection_write_ip (u_char *ip_packet) { #if defined(INJECT_USING_RAW_SOCKETS) || defined(INJECT_USING_LINK_LAYER) int i; u_int16_t packet_size = ntohs(*(u_int16_t*)(ip_packet+2)); #endif #if defined(INJECT_USING_RAW_SOCKETS) int network; /* network initialization */ if ((network = libnet_open_raw_sock(IPPROTO_RAW)) < 0) { return WIRE_ERR_PKTD_INJECTION_OPEN; /* packet injection */ } else if ((i = libnet_write_ip (network, ip_packet, packet_size)) < packet_size) { return WIRE_ERR_PKTD_INJECTION_WRITE_IP; /* shut down the interface */ } else if (libnet_close_raw_sock (network) < 0) { return WIRE_ERR_PKTD_INJECTION_CLOSE; } return WIRE_ERR_NONE; #elif defined(INJECT_USING_LINK_LAYER) char buffer[LIBNET_ETH_H+IP_MAXPACKET]; struct in_addr in; int size = 1024; struct libnet_link_int *network; /* pointer to link interface struct */ char *interface = NULL; /* pointer to the device to use */ struct sockaddr_in sin; char errbuf[1024]; struct ether_addr remote_eth, *tmp_eth; /* network initialization */ if (libnet_select_device(&sin, &interface, errbuf) == -1) { return WIRE_ERR_PKTD_NO_WRITE_DEVICE_ACCESS; } if ((network = libnet_open_link_interface(interface, errbuf)) == NULL) { return WIRE_ERR_PKTD_INJECTION_OPEN; } /* get local ethernet address */ if ((tmp_eth = libnet_get_hwaddr(network, interface, errbuf)) == NULL) { (void)libnet_close_link_interface(network); return WIRE_ERR_PKTD_INJECTION_OPEN; } memcpy (&local_eth, tmp_eth, 6); debug3 ("injection_write_ip: the local ethernet address is %s\n", ether_ntoa(&local_eth)); /* get remote ethernet address (the packet is already in network order) */ in.s_addr = *(u_int32_t*)(ip_packet+16); /* try to get the remote MAC address from the ARP cache */ if (get_mac_address (in, buffer, size) < 0) { /* MAC address of the IP address not in ARP cache */ /* get the gateway needed to reach the destination */ struct in_addr gw; if (get_gateway (in, &gw) < 0) { debug3 ("injection_write_ip: can't find MAC nor gateway for %s\n", inet_ntoa(in)); (void)libnet_close_link_interface(network); return WIRE_ERR_PKTD_INJECTION_WRITE_IP; } /* get the gateway's ethernet address */ if (get_mac_address (gw, buffer, size) < 0) { debug3 ("injection_write_ip: can't find MAC for %s's ", inet_ntoa(in)); debug3 ("gateway (%s)\n", inet_ntoa(gw)); /* XXX: This case means typically the destination host is in * the same network than the source, but the destination MAC * address is not in the local ARP cache. Getting a local * MAC address requires implementing ARP, which we won't do * at this moment */ (void)libnet_close_link_interface(network); return WIRE_ERR_PKTD_INJECTION_WRITE_IP; } debug3 ("injection_write_ip: IP address %s can be reached ", inet_ntoa(in)); debug3 ("through gateway %s (%s)\n", inet_ntoa(gw), buffer); } else { debug3 ("injection_write_ip: IP address %s corresponds to %s\n", inet_ntoa(in), buffer); } if ((tmp_eth = ether_aton (buffer)) == NULL) { (void)libnet_close_link_interface(network); return WIRE_ERR_PKTD_INJECTION_WRITE_IP; } memcpy (&remote_eth, tmp_eth, 6); /* build ethernet header and use IP packet as payload */ #if (defined(bsdi) || defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(__FreeBSD__)) libnet_build_ethernet(&(remote_eth.octet[0]), &(local_eth.octet[0]), ETHERTYPE_IP, NULL, 0, buffer); #else libnet_build_ethernet(&(remote_eth.ether_addr_octet[0]), &(local_eth.ether_addr_octet[0]), ETHERTYPE_IP, NULL, 0, buffer); #endif memcpy (buffer+LIBNET_ETH_H, ip_packet, packet_size); packet_size += LIBNET_ETH_H; /* inject the packet */ if ((i = libnet_write_link_layer (network, interface, buffer, packet_size)) < packet_size) { (void)libnet_close_link_interface(network); return WIRE_ERR_PKTD_INJECTION_WRITE_IP; } /* shut down the interface */ (void)libnet_close_link_interface(network); return WIRE_ERR_NONE; #else /* INJECT_USING_LINK_LAYER */ return(0); #endif /* INJECT_USING_LINK_LAYER */ }