int main(int argc, char *argv[]) { int ch, rv, action = VND_CONFIG; while ((ch = getopt(argc, argv, "Fcf:lrt:uvz")) != -1) { switch (ch) { case 'F': force = 1; break; case 'c': action = VND_CONFIG; break; case 'f': if (setdisktab(optarg) == -1) usage(); break; case 'l': action = VND_GET; break; case 'r': readonly = 1; break; case 't': tabname = optarg; break; case 'u': action = VND_UNCONFIG; break; case 'v': verbose = 1; break; case 'z': compressed = 1; readonly = 1; break; default: case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (action == VND_CONFIG) { if ((argc < 2 || argc > 3) || (argc == 3 && tabname != NULL)) usage(); rv = config(argv[0], argv[1], (argc == 3) ? argv[2] : NULL, action); } else if (action == VND_UNCONFIG) { if (argc != 1 || tabname != NULL) usage(); rv = config(argv[0], NULL, NULL, action); } else { /* VND_GET */ int n, v; const char *vn; char path[64]; if (argc != 0 && argc != 1) usage(); vn = argc ? argv[0] : "vnd0"; v = opendisk(vn, O_RDONLY, path, sizeof(path), 0); if (v == -1) err(1, "open: %s", vn); if (argc) show(v, -1); else { DIR *dirp; struct dirent *dp; __BITMAP_TYPE(, uint32_t, 65536) bm; __BITMAP_ZERO(&bm); if ((dirp = opendir(_PATH_DEV)) == NULL) err(1, "opendir: %s", _PATH_DEV); while ((dp = readdir(dirp)) != NULL) { if (strncmp(dp->d_name, "rvnd", 4) != 0) continue; n = atoi(dp->d_name + 4); if (__BITMAP_ISSET(n, &bm)) continue; __BITMAP_SET(n, &bm); show(v, n); } closedir(dirp); } close(v); rv = 0; } return rv; }
/* * Check whether the port picked by the port randomizer is available * and whether KAUTH approves of our choice. This part of the code * shamelessly copied from in_pcb.c. */ static bool check_suitable_port(uint16_t port, struct inpcb_hdr *inp_hdr, kauth_cred_t cred) { struct inpcbtable * const table = inp_hdr->inph_table; #ifdef INET vestigial_inpcb_t vestigial; #endif int error; #ifdef INET6 struct socket *so; int wild = 0; #endif DPRINTF("%s called for argument %d\n", __func__, port); switch (inp_hdr->inph_af) { #ifdef INET case AF_INET: { /* IPv4 */ struct inpcb *inp = (struct inpcb *)(void *)inp_hdr; struct inpcb *pcb; struct sockaddr_in sin; if (__BITMAP_ISSET(port, &inet4_reserve)) return false; sin.sin_addr = inp->inp_laddr; pcb = in_pcblookup_port(table, sin.sin_addr, htons(port), 1, &vestigial); DPRINTF("%s in_pcblookup_port returned %p and " "vestigial.valid %d\n", __func__, pcb, vestigial.valid); if ((!pcb) && (!vestigial.valid)) { enum kauth_network_req req; /* We have a free port. Check with the secmodel. */ if (inp->inp_flags & INP_LOWPORT) { #ifndef IPNOPRIVPORTS req = KAUTH_REQ_NETWORK_BIND_PRIVPORT; #else req = KAUTH_REQ_NETWORK_BIND_PORT; #endif } else req = KAUTH_REQ_NETWORK_BIND_PORT; sin.sin_port = port; error = kauth_authorize_network(cred, KAUTH_NETWORK_BIND, req, inp->inp_socket, &sin, NULL); DPRINTF("%s kauth_authorize_network returned %d\n", __func__, error); if (error == 0) { DPRINTF("%s port approved\n", __func__); return true; /* KAUTH agrees */ } } break; } #endif #ifdef INET6 case AF_INET6: { /* IPv6 */ struct in6pcb *in6p = (struct in6pcb *)(void *)inp_hdr; struct sockaddr_in6 sin6; void *t; if (__BITMAP_ISSET(port, &inet6_reserve)) return false; sin6.sin6_addr = in6p->in6p_laddr; so = in6p->in6p_socket; /* XXX: this is redundant when called from in6_pcbbind */ if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || (so->so_options & SO_ACCEPTCONN) == 0)) wild = 1; #ifdef INET if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) { t = in_pcblookup_port(table, *(struct in_addr *)&sin6.sin6_addr.s6_addr32[3], htons(port), wild, &vestigial); if (!t && vestigial.valid) { DPRINTF("%s in_pcblookup_port returned " "a result\n", __func__); return false; } } else #endif { t = in6_pcblookup_port(table, &sin6.sin6_addr, htons(port), wild, &vestigial); if (!t && vestigial.valid) { DPRINTF("%s in6_pcblookup_port returned " "a result\n", __func__); return false; } } if (t == NULL) { enum kauth_network_req req; /* We have a free port. Check with the secmodel. */ if (in6p->in6p_flags & IN6P_LOWPORT) { #ifndef IPNOPRIVPORTS req = KAUTH_REQ_NETWORK_BIND_PRIVPORT; #else req = KAUTH_REQ_NETWORK_BIND_PORT; #endif } else { req = KAUTH_REQ_NETWORK_BIND_PORT; } sin6.sin6_port = port; error = kauth_authorize_network(cred, KAUTH_NETWORK_BIND, req, so, &sin6, NULL); if (error) { /* Secmodel says no. Keep looking. */ DPRINTF("%s secmodel says no\n", __func__); return false; } DPRINTF("%s port approved\n", __func__); return true; } break; } #endif default: DPRINTF("%s unknown address family\n", __func__); return false; } return false; }