2 * radclient General radius packet debug tool.
7 static const char rcsid[] = "$Id$";
11 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
23 # include <sys/select.h>
35 #include "libradius.h"
38 static int retries = 10;
39 static float timeout = 3;
40 static const char *secret = "secret";
41 static int do_output = 1;
44 * Read valuepairs from the fp up to End-Of-File.
46 static VALUE_PAIR *readvp(FILE *fp)
57 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
61 if ((vp = pairread(&p, &last_token)) == NULL) {
62 librad_perror("radclient:");
67 } while (last_token == T_COMMA);
69 return error ? NULL: list;
72 static void usage(void)
74 fprintf(stderr, "Usage: radclient [-c count] [-d raddb] [-f file] [-r retries] [-t timeout]\n [-i id] [-qvx] server acct|auth <secret>\n");
76 fprintf(stderr, " -c count Send 'count' packets.\n");
77 fprintf(stderr, " -d raddb Set dictionary directory.\n");
78 fprintf(stderr, " -f file Read packets from file, not stdin.\n");
79 fprintf(stderr, " -r retries If timeout, retry sending the packet 'retires' times.\n");
80 fprintf(stderr, " -t timeout Wait 'timeout' seconds before retrying.\n");
81 fprintf(stderr, " -i id Set request id to 'id'. Values may be 0..255\n");
82 fprintf(stderr, " -q Do not print anything out.\n");
83 fprintf(stderr, " -v Show program version information.\n");
84 fprintf(stderr, " -x Debugging mode.\n");
89 static int getport(const char *name)
93 svp = getservbyname (name, "udp");
98 return ntohs(svp->s_port);
101 static int send_packet(RADIUS_PACKET *req, RADIUS_PACKET **rep)
106 for (i = 0; i < retries; i++) {
109 rad_send(req, secret);
111 /* And wait for reply, timing out as necessary */
113 FD_SET(req->sockfd, &rdfdesc);
115 tv.tv_sec = (int)timeout;
116 tv.tv_usec = 1000000 * (timeout - (int)timeout);
118 /* Something's wrong if we don't get exactly one fd. */
119 if (select(req->sockfd + 1, &rdfdesc, NULL, NULL, &tv) != 1) {
123 *rep = rad_recv(req->sockfd);
126 } else { /* NULL: couldn't receive the packet */
127 librad_perror("radclient:");
132 /* No response or no data read (?) */
134 fprintf(stderr, "radclient: no response from server\n");
138 if (rad_decode(*rep, req, secret) != 0) {
139 librad_perror("rad_decode");
143 /* libradius debug already prints out the value pairs for us */
144 if (!librad_debug && do_output) {
145 printf("Received response ID %d, code %d, length = %d\n",
146 (*rep)->id, (*rep)->code, (*rep)->data_len);
147 vp_printlist(stdout, (*rep)->vps);
153 int main(int argc, char **argv)
156 RADIUS_PACKET *rep = NULL;
160 const char *radius_dir = RADDBDIR;
161 char *filename = NULL;
169 id = ((int)getpid() & 0xff);
171 while ((c = getopt(argc, argv, "c:d:f:hi:qt:r:xv")) != EOF) switch(c) {
173 if (!isdigit(*optarg)) usage();
174 count = atoi(optarg);
189 if (!isdigit(*optarg)) usage();
190 retries = atoi(optarg);
193 if (!isdigit(*optarg)) usage();
195 if ((id < 0) || (id > 255)) {
200 if (!isdigit(*optarg)) usage();
201 timeout = atof(optarg);
204 printf("radclient: $Id$ built on " __DATE__ "\n");
212 argc -= (optind - 1);
213 argv += (optind - 1);
219 if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
220 librad_perror("radclient");
224 if ((req = rad_alloc(1)) == NULL) {
225 librad_perror("radclient");
232 * Strip port from hostname if needed.
234 if ((p = strchr(argv[1], ':')) != NULL) {
240 * See what kind of request we want to send.
242 if (strcmp(argv[2], "auth") == 0) {
243 if (port == 0) port = getport("radius");
244 if (port == 0) port = PW_AUTH_UDP_PORT;
245 req->code = PW_AUTHENTICATION_REQUEST;
246 } else if (strcmp(argv[2], "acct") == 0) {
247 if (port == 0) port = getport("radacct");
248 if (port == 0) port = PW_ACCT_UDP_PORT;
249 req->code = PW_ACCOUNTING_REQUEST;
250 } else if (isdigit(argv[2][0])) {
251 if (port == 0) port = PW_AUTH_UDP_PORT;
252 port = atoi(argv[2]);
260 req->dst_port = port;
261 req->dst_ipaddr = ip_getaddr(argv[1]);
262 if (req->dst_ipaddr == 0) {
263 librad_perror("radclient: %s: ", argv[1]);
270 if (argv[3]) secret = argv[3];
274 * Maybe read them, from stdin, if there's no
275 * filename, or if the filename is '-'.
277 if (filename && (strcmp(filename, "-") != 0)) {
278 fp = fopen(filename, "r");
280 fprintf(stderr, "radclient: Error opening %s: %s\n",
281 filename, strerror(errno));
288 if ((req->vps = readvp(fp)) == NULL) {
295 if ((req->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
296 perror("radclient: socket: ");
300 vp = pairfind(req->vps, PW_PASSWORD);
302 strNcpy(password, (char *)vp->strvalue, sizeof(vp->length));
308 * Loop, sending the packet N times.
310 for (loop = 0; loop < count; loop++) {
314 * If we've already sent a packet, free up the old
315 * one, and ensure that the next packet has a unique
316 * ID and authentication vector.
321 if (*password != '\0') {
322 vp = pairfind(req->vps, PW_PASSWORD);
324 strNcpy((char *)vp->strvalue, password,
326 vp->length = strlen(password);
330 librad_md5_calc(req->vector, req->vector,
331 sizeof(req->vector));
333 send_packet(req, &rep);