int main(int argc, char **argv) { krb5_context context; krb5_error_code ret; krb5_addresses addrs; int optidx = 0; setprogname (argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optidx; argv += optidx; ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); ret = krb5_get_all_client_addrs (context, &addrs); if (ret) krb5_err (context, 1, ret, "krb5_get_all_client_addrs"); printf ("client addresses\n"); print_addresses (context, &addrs); krb5_free_addresses (context, &addrs); ret = krb5_get_all_server_addrs (context, &addrs); if (ret) krb5_err (context, 1, ret, "krb5_get_all_server_addrs"); printf ("server addresses\n"); print_addresses (context, &addrs); krb5_free_addresses (context, &addrs); return 0; }
static int doit (krb5_keytab keytab, int port) { krb5_error_code ret; int *sockets; int maxfd; krb5_realm *realms; krb5_addresses addrs; krb5_address *my_addrp; unsigned n, i; fd_set real_fdset; struct sockaddr_storage __ss; struct sockaddr *sa = (struct sockaddr *)&__ss; #ifdef INETD_SUPPORT int fdz; int from_inetd; socklen_t fromlen; krb5_address my_addr; struct sockaddr_storage __local; struct sockaddr *localsa = (struct sockaddr *)&__local; #endif ret = krb5_get_default_realms(context, &realms); if (ret) krb5_err (context, 1, ret, "krb5_get_default_realms"); #ifdef INETD_SUPPORT fromlen = sizeof __ss; from_inetd = (getsockname(0, sa, &fromlen) == 0); if (!from_inetd) { #endif if (explicit_addresses.len) { addrs = explicit_addresses; } else { ret = krb5_get_all_server_addrs (context, &addrs); if (ret) krb5_err (context, 1, ret, "krb5_get_all_server_addrs"); } n = addrs.len; sockets = malloc (n * sizeof(*sockets)); if (sockets == NULL) krb5_errx (context, 1, "out of memory"); maxfd = -1; FD_ZERO(&real_fdset); for (i = 0; i < n; ++i) { krb5_socklen_t sa_size = sizeof(__ss); krb5_addr2sockaddr (context, &addrs.val[i], sa, &sa_size, port); sockets[i] = socket (sa->sa_family, SOCK_DGRAM, 0); if (sockets[i] < 0) krb5_err (context, 1, errno, "socket"); if (bind (sockets[i], sa, sa_size) < 0) { char str[128]; size_t len; int save_errno = errno; ret = krb5_print_address (&addrs.val[i], str, sizeof(str), &len); if (ret) strlcpy(str, "unknown address", sizeof(str)); krb5_warn (context, save_errno, "bind(%s)", str); continue; } maxfd = max (maxfd, sockets[i]); if (maxfd >= FD_SETSIZE) krb5_errx (context, 1, "fd too large"); FD_SET(sockets[i], &real_fdset); } #ifdef INETD_SUPPORT } else { n = 1; maxfd = 0; fdz = 0; sockets = &fdz; FD_ZERO(&real_fdset); FD_SET(0, &real_fdset); } #endif if (maxfd == -1) krb5_errx (context, 1, "No sockets!"); while(exit_flag == 0) { krb5_ssize_t retx; fd_set fdset = real_fdset; retx = select (maxfd + 1, &fdset, NULL, NULL, NULL); if (retx < 0) { if (errno == EINTR) continue; else krb5_err (context, 1, errno, "select"); } for (i = 0; i < n; ++i) if (FD_ISSET(sockets[i], &fdset)) { u_char buf[BUFSIZ]; socklen_t addrlen = sizeof(__ss); retx = recvfrom(sockets[i], buf, sizeof(buf), 0, sa, &addrlen); if (retx < 0) { if(errno == EINTR) break; else krb5_err (context, 1, errno, "recvfrom"); } #ifdef INETD_SUPPORT if (from_inetd) { socklen_t loclen = sizeof(__local); int ret2; ret2 = get_local_addr(sa, addrlen, localsa, &loclen); if (ret2 < 0) krb5_errx (context, errno, "get_local_addr"); ret2 = krb5_sockaddr2address(context, localsa, &my_addr); if (ret2) krb5_errx (context, ret2, "krb5_sockaddr2address"); my_addrp = &my_addr; } else #endif my_addrp = &addrs.val[i]; process (realms, keytab, sockets[i], my_addrp, sa, addrlen, buf, retx); #ifdef INETD_SUPPORT if (from_inetd) { krb5_free_address(context, &my_addr); } #endif } #ifdef INETD_SUPPORT if (from_inetd) break; #endif } for (i = 0; i < n; ++i) close(sockets[i]); free(sockets); #ifdef INETD_SUPPORT if (!from_inetd) #endif krb5_free_addresses (context, &addrs); krb5_free_host_realm (context, realms); krb5_free_context (context); return 0; }