/* * Obtain a socket to talk to this guy. * Not entirely trivial - this can be both an established * (incoming) connection, or one that we should establish. * * Note, we do not support transmission on the incoming * connection yet. */ static isns_socket_t * isns_scn_get_socket(isns_scn_t *scn) { isns_scn_funnel_t *f, *best = NULL; isns_socket_t *sock; unsigned int worst = 0, loops = 0, nfunnels; /* Keep it simple for now */ if ((f = scn->scn_current_funnel) != NULL && f->scn_socket) { if (!f->scn_bad) return f->scn_socket; /* Oops, we've seen timeouts on this socket. */ isns_socket_free(f->scn_socket); f->scn_socket = NULL; } again: nfunnels = 0; for (f = scn->scn_funnels; f; f = f->scn_next) { unsigned int badness = f->scn_bad; if (!best || badness < best->scn_bad) best = f; if (badness > worst) worst = badness; nfunnels++; } if (!best) return NULL; sock = isns_connect_to_portal(&best->scn_portal); if (sock == NULL) { /* Make sure we try each funnel exactly once */ best->scn_bad = worst + 1; if (++loops < nfunnels) goto again; return NULL; } /* Set the security context */ isns_socket_set_security_ctx(sock, isns_default_security_context(1)); isns_debug_scn("SCN: %s using portal %s\n", scn->scn_name, isns_portal_string(&best->scn_portal)); scn->scn_current_funnel = best; best->scn_socket = sock; return sock; }
int isns_enumerate_portals(isns_portal_info_t *result, unsigned int max) { char buffer[8192], *end, *ptr; struct ifconf ifc; unsigned int nportals = 0; int fd = -1; if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { isns_error("%s: no socket - %m\n", __FUNCTION__); return 0; } ifc.ifc_buf = buffer; ifc.ifc_len = sizeof(buffer); if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { isns_error("ioctl(SIOCGIFCONF): %m\n"); goto out; } ptr = buffer; end = buffer + ifc.ifc_len; while (ptr < end) { struct ifreq ifr; struct sockaddr_storage ifaddr; isns_portal_info_t portal; int ifflags; memcpy(&ifr, ptr, sizeof(ifr)); ptr += sizeof(ifr); /* Get the interface addr */ memcpy(&ifaddr, &ifr.ifr_addr, sizeof(ifr.ifr_addr)); if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { isns_error("ioctl(%s, SIOCGIFFLAGS): %m\n", ifr.ifr_name); continue; } ifflags = ifr.ifr_flags; if ((ifflags & IFF_UP) == 0) continue; if ((ifflags & IFF_LOOPBACK) != 0) continue; if (!isns_portal_from_sockaddr(&portal, &ifaddr)) continue; isns_debug_socket("Got interface %u: %s %s\n", nportals, ifr.ifr_name, isns_portal_string(&portal)); if (nportals < max) result[nportals++] = portal; } out: if (fd >= 0) close(fd); return nportals; }