📄 radclient.c
字号:
* Duplicate found. Serious error! */ if (rbtree_insert(request_tree, radclient) == 0) { assert(0 == 1); } } else { /* radclient->request->id >= 0 */ time_t now = time(NULL); /* * FIXME: Accounting packets are never retried! * The Acct-Delay-Time attribute is updated to * reflect the delay, and the packet is re-sent * from scratch! */ /* * Not time for a retry, do so. */ if ((now - radclient->timestamp) < timeout) { /* * When we walk over the tree sending * packets, we update the minimum time * required to sleep. */ if ((sleep_time == -1) || (sleep_time > (now - radclient->timestamp))) { sleep_time = now - radclient->timestamp; } return 0; } /* * We're not trying later, maybe the packet is done. */ if (radclient->tries == retries) { rbnode_t *node; assert(radclient->request->id >= 0); /* * Delete the request from the tree of * outstanding requests. */ node = rbtree_find(request_tree, radclient); assert(node != NULL); fprintf(stderr, "radclient: no response from server for ID %d\n", radclient->request->id); rbtree_delete(request_tree, node); /* * Normally we mark it "done" when we've received * the response, but this is a special case. */ if (radclient->resend == resend_count) { radclient->done = 1; } totallost++; return -1; } /* * We are trying later. */ radclient->timestamp = now; radclient->tries++; } /* * Send the packet. */ rad_send(radclient->request, NULL, secret); return 0;}/* * Receive one packet, maybe. */static int recv_one_packet(int wait_time){ fd_set set; struct timeval tv; radclient_t myclient, *radclient; RADIUS_PACKET myrequest, *reply; rbnode_t *node; /* And wait for reply, timing out as necessary */ FD_ZERO(&set); FD_SET(sockfd, &set); if (wait_time <= 0) { tv.tv_sec = 0; } else { tv.tv_sec = wait_time; } tv.tv_usec = 0; /* * No packet was received. */ if (select(sockfd + 1, &set, NULL, NULL, &tv) != 1) { return 0; } /* * Look for the packet. */ reply = rad_recv(sockfd); if (!reply) { fprintf(stderr, "radclient: received bad packet\n"); return -1; /* bad packet */ } myclient.request = &myrequest; myrequest.id = reply->id; myrequest.dst_ipaddr = reply->src_ipaddr; myrequest.dst_port = reply->src_port; node = rbtree_find(request_tree, &myclient); if (!node) { fprintf(stderr, "radclient: received response to request we did not send.\n"); return -1; /* got reply to packet we didn't send */ } radclient = rbtree_node2data(request_tree, node); assert(radclient != NULL); rbtree_delete(request_tree, node); assert(radclient->request->id == -1); assert(radclient->request->data == NULL); assert(radclient->reply == NULL); radclient->reply = reply; /* * FIXME: Do stuff to process the reply. */ if (rad_decode(reply, radclient->request, secret) != 0) { librad_perror("rad_decode"); totallost++; return -1; } /* libradius debug already prints out the value pairs for us */ if (!librad_debug && do_output) { printf("Received response ID %d, code %d, length = %d\n", reply->id, reply->code, reply->data_len); vp_printlist(stdout, reply->vps); } if (reply->code != PW_AUTHENTICATION_REJECT) { totalapp++; } else { totaldeny++; } if (radclient->reply) rad_free(&radclient->reply); /* * Once we've sent the packet as many times as requested, * mark it done. */ if (radclient->resend == resend_count) { assert((node = rbtree_find(request_tree, radclient)) == NULL); radclient->done = 1; } return 0;}static int getport(const char *name){ struct servent *svp; svp = getservbyname (name, "udp"); if (!svp) { return 0; } return ntohs(svp->s_port);}int main(int argc, char **argv){ char *p; int c; const char *radius_dir = RADDBDIR; char filesecret[256]; FILE *fp; int do_summary = 0; radclient_t *this; librad_debug = 0; filename_tree = rbtree_create(filename_cmp, NULL, 0); if (!filename_tree) { fprintf(stderr, "radclient: Out of memory\n"); exit(1); } request_tree = rbtree_create(request_cmp, request_free, 0); if (!request_tree) { fprintf(stderr, "radclient: Out of memory\n"); exit(1); } while ((c = getopt(argc, argv, "c:d:f:hi:qst:r:S:xv")) != EOF) switch(c) { case 'c': if (!isdigit((int) *optarg)) usage(); resend_count = atoi(optarg); break; case 'd': radius_dir = optarg; break; case 'f': rbtree_insert(filename_tree, optarg); break; case 'q': do_output = 0; break; case 'x': librad_debug++; break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); if ((retries == 0) || (retries > 1000)) usage(); break; case 'i': if (!isdigit((int) *optarg)) usage(); last_used_id = atoi(optarg); if ((last_used_id < 0) || (last_used_id > 255)) { usage(); } break; case 's': do_summary = 1; break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': printf("radclient: $Id: radclient.c,v 1.72.2.1 2004/06/02 15:31:53 aland Exp $ built on " __DATE__ " at " __TIME__ "\n"); exit(0); break; case 'S': fp = fopen(optarg, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", optarg, strerror(errno)); exit(1); } if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { fprintf(stderr, "radclient: Error reading %s: %s\n", optarg, strerror(errno)); exit(1); } fclose(fp); /* truncate newline */ p = filesecret + strlen(filesecret) - 1; while ((p >= filesecret) && (*p < ' ')) { *p = '\0'; --p; } if (strlen(filesecret) < 2) { fprintf(stderr, "radclient: Secret in %s is too short\n", optarg); exit(1); } secret = filesecret; break; case 'h': default: usage(); break; } argc -= (optind - 1); argv += (optind - 1); if ((argc < 3) || ((secret == NULL) && (argc < 4))) { usage(); } if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) { librad_perror("radclient"); return 1; } /* * Strip port from hostname if needed. */ if ((p = strchr(argv[1], ':')) != NULL) { *p++ = 0; server_port = atoi(p); } /* * Grab the socket. */ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("radclient: socket: "); exit(1); } memset(radius_id, 0, sizeof(radius_id)); /* * See what kind of request we want to send. */ if (strcmp(argv[2], "auth") == 0) { if (server_port == 0) server_port = getport("radius"); if (server_port == 0) server_port = PW_AUTH_UDP_PORT; packet_code = PW_AUTHENTICATION_REQUEST; } else if (strcmp(argv[2], "acct") == 0) { if (server_port == 0) server_port = getport("radacct"); if (server_port == 0) server_port = PW_ACCT_UDP_PORT; packet_code = PW_ACCOUNTING_REQUEST; do_summary = 0; } else if (strcmp(argv[2], "status") == 0) { if (server_port == 0) server_port = getport("radius"); if (server_port == 0) server_port = PW_AUTH_UDP_PORT; packet_code = PW_STATUS_SERVER; } else if (strcmp(argv[2], "disconnect") == 0) { if (server_port == 0) server_port = PW_POD_UDP_PORT; packet_code = PW_DISCONNECT_REQUEST; } else if (strcmp(argv[2], "auto") == 0) { packet_code = -1; } else if (isdigit((int) argv[2][0])) { if (server_port == 0) server_port = getport("radius"); if (server_port == 0) server_port = PW_AUTH_UDP_PORT; packet_code = atoi(argv[2]); } else { usage(); } /* * Resolve hostname. */ server_ipaddr = ip_getaddr(argv[1]); if (server_ipaddr == INADDR_NONE) { fprintf(stderr, "radclient: Failed to find IP address for host %s\n", argv[1]); exit(1); } /* * Add the secret. */ if (argv[3]) secret = argv[3]; /* * If no '-f' is specified, we're reading from stdin. */ if (rbtree_num_elements(filename_tree) == 0) { rbtree_insert(filename_tree, "-"); } /* * Walk over the list of filenames, creating the requests. */ if (rbtree_walk(filename_tree, filename_walk, InOrder) != 0) { exit(1); } /* * No packets read. Die. */ if (!radclient_head) { fprintf(stderr, "radclient: Nothing to send.\n"); exit(1); } /* * Walk over the list of packets, sanity checking * everything. */ for (this = radclient_head; this != NULL; this = this->next) { if (radclient_sane(this) != 0) { exit(1); } } if (last_used_id < 0) last_used_id = getpid() & 0xff; /* * Walk over the packets to send, until * we're all done. * * FIXME: This currently busy-loops until it receives * all of the packets. It should really have some sort of * send packet, get time to wait, select for time, etc. * loop. */ do { radclient_t *next; const char *filename = NULL; done = 1; sleep_time = -1; /* * Walk over the packets, sending them. */ for (this = radclient_head; this != NULL; this = next) { next = this->next; /* * If there's a packet to receive, * receive it, but don't wait for a * packet. */ recv_one_packet(0); /* * This packet is done. Delete it. */ if (this->done) { radclient_free(this); continue; } /* * Packets from multiple '-f' are sent * in parallel. Packets from one file * are sent in series. */ if (this->filename != filename) { filename = this->filename; /* * Send the current packet. */ send_one_packet(this); /* * If we haven't sent this packet * often enough, we're not done, * and we shouldn't sleep. */ if (this->resend < resend_count) { done = 0; sleep_time = 0; } } else { /* haven't sent this packet, we're not done */ assert(this->done == 0); assert(this->reply == NULL); done = 0; } } /* * Still have outstanding requests. */ if (rbtree_num_elements(request_tree) > 0) { done = 0; } else { sleep_time = 0; } /* * Nothing to do until we receive a request, so * sleep until then. Once we receive one packet, * we go back, and walk through the whole list again, * sending more packets (if necessary), and updating * the sleep time. */ if (!done && (sleep_time > 0)) { recv_one_packet(sleep_time); } } while (!done); rbtree_free(filename_tree); rbtree_free(request_tree); if (do_summary) { printf("\n\t Total approved auths: %d\n", totalapp); printf("\t Total denied auths: %d\n", totaldeny); printf("\t Total lost auths: %d\n", totallost); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -