1 /* 2 * Copyright (c) 2008 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Sepherosa Ziehau <sepherosa@gmail.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/tools/tools/netrate/pktgenctl/pktgenctl.c,v 1.3 2008/03/29 11:45:46 sephe Exp $ 35 */ 36 37 #include <sys/types.h> 38 #include <sys/ioctl.h> 39 #include <sys/stat.h> 40 #include <sys/socket.h> 41 42 #include <arpa/inet.h> 43 #include <netinet/in.h> 44 #include <net/if.h> 45 #include <net/if_dl.h> 46 #include <net/ethernet.h> 47 48 #include <err.h> 49 #include <fcntl.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 55 #include "pktgen/pktgen.h" 56 57 #define PKTGEN_DEVPATH "/dev/pktg0" 58 59 #define DEFAULT_SPORT 3001 60 #define DEFAULT_DPORT 3000 61 62 #define INDST_MASK 0x1 63 #define INSRC_MASK 0x2 64 #define EADDR_MASK 0x4 65 #define IFACE_MASK 0x8 66 #define DATALEN_MASK 0x10 67 #define SPORT_MASK 0x20 68 #define DPORT_MASK 0x40 69 #define CPUID_MASK 0x80 70 #define DURATION_MASK 0x100 71 #define YIELD_MASK 0x200 72 73 #define MASK_NEEDED (INDST_MASK | INSRC_MASK | EADDR_MASK | IFACE_MASK) 74 75 static void 76 usage(void) 77 { 78 fprintf(stderr, "pktgenctl -d dst_inaddr[,ndst] -s src_inaddr[,nsrc] " 79 "-e (gw_eaddr|dst_eaddr) -i iface " 80 "[-p src_port[,nsport]] [-P dst_port[,ndport]] " 81 "[-m data_len] [-c cpuid] [-l duration] [-y yield]\n"); 82 exit(1); 83 } 84 85 static int 86 get_range(char *str) 87 { 88 char *ptr; 89 90 ptr = strstr(str, ","); 91 if (ptr == NULL) { 92 return 0; 93 } else { 94 *ptr = '\0'; 95 return atoi(ptr + 1); 96 } 97 } 98 99 int 100 main(int argc, char *argv[]) 101 { 102 struct pktgen_conf conf; 103 struct sockaddr *sa; 104 struct sockaddr_in *dst_sin, *src_sin; 105 struct sockaddr_dl sdl; 106 char eaddr_str[32]; 107 uint32_t arg_mask = 0; 108 int fd, c, n; 109 110 memset(&conf, 0, sizeof(conf)); 111 112 conf.pc_cpuid = 0; 113 conf.pc_duration = 10; 114 conf.pc_datalen = 10; 115 116 sa = &conf.pc_dst_lladdr; 117 sa->sa_family = AF_LINK; 118 sa->sa_len = ETHER_ADDR_LEN; 119 120 dst_sin = &conf.pc_dst; 121 dst_sin->sin_family = AF_INET; 122 dst_sin->sin_port = htons(DEFAULT_DPORT); 123 124 src_sin = &conf.pc_src; 125 src_sin->sin_family = AF_INET; 126 src_sin->sin_port = htons(DEFAULT_SPORT); 127 128 while ((c = getopt(argc, argv, "d:s:e:i:p:P:m:c:l:y:")) != -1) { 129 switch (c) { 130 case 'd': 131 conf.pc_ndaddr = get_range(optarg); 132 n = inet_pton(AF_INET, optarg, 133 &dst_sin->sin_addr.s_addr); 134 if (n == 0) 135 errx(1, "-d: invalid inet address"); 136 else if (n < 0) 137 err(1, "-d"); 138 arg_mask |= INDST_MASK; 139 break; 140 141 case 's': 142 conf.pc_nsaddr = get_range(optarg); 143 n = inet_pton(AF_INET, optarg, 144 &src_sin->sin_addr.s_addr); 145 if (n == 0) 146 errx(1, "-s: invalid inet address"); 147 else if (n < 0) 148 err(1, "-s"); 149 arg_mask |= INSRC_MASK; 150 break; 151 152 case 'e': 153 strcpy(eaddr_str, "if0."); 154 strlcpy(&eaddr_str[strlen("if0.")], optarg, 155 sizeof(eaddr_str) - strlen("if0.")); 156 157 memset(&sdl, 0, sizeof(sdl)); 158 sdl.sdl_len = sizeof(sdl); 159 link_addr(eaddr_str, &sdl); 160 bcopy(LLADDR(&sdl), sa->sa_data, ETHER_ADDR_LEN); 161 arg_mask |= EADDR_MASK; 162 break; 163 164 case 'i': 165 strlcpy(conf.pc_ifname, optarg, sizeof(conf.pc_ifname)); 166 arg_mask |= IFACE_MASK; 167 break; 168 169 case 'p': 170 conf.pc_nsport = get_range(optarg); 171 src_sin->sin_port = htons(atoi(optarg)); 172 arg_mask |= SPORT_MASK; 173 break; 174 175 case 'P': 176 conf.pc_ndport = get_range(optarg); 177 dst_sin->sin_port = htons(atoi(optarg)); 178 arg_mask |= DPORT_MASK; 179 break; 180 181 case 'm': 182 conf.pc_datalen = atoi(optarg); 183 arg_mask |= DATALEN_MASK; 184 break; 185 186 case 'c': 187 conf.pc_cpuid = atoi(optarg); 188 arg_mask |= CPUID_MASK; 189 break; 190 191 case 'l': 192 conf.pc_duration = atoi(optarg); 193 arg_mask |= DURATION_MASK; 194 break; 195 196 case 'y': 197 conf.pc_yield = atoi(optarg); 198 arg_mask |= YIELD_MASK; 199 break; 200 } 201 } 202 203 if ((arg_mask & MASK_NEEDED) != MASK_NEEDED) 204 usage(); 205 206 fd = open(PKTGEN_DEVPATH, O_RDONLY); 207 if (fd < 0) 208 err(1, "open(" PKTGEN_DEVPATH ")"); 209 210 if (ioctl(fd, PKTGENSCONF, &conf) < 0) 211 err(1, "ioctl(PKTGENSCONF)"); 212 213 if (ioctl(fd, PKTGENSTART) < 0) 214 err(1, "ioctl(PKTGENSTART)"); 215 216 close(fd); 217 exit(0); 218 } 219