/** Checks if provided address is local address * * @param addr an %AF_INET or %AF_INET6 address * @return 0 if local, 1 if not local, -1 on failure. */ static int rc_ipaddr_local(const struct sockaddr *addr) { int temp_sock, res, serrno; struct sockaddr tmpaddr; memcpy(&tmpaddr, addr, SA_LEN(addr)); temp_sock = socket(addr->sa_family, SOCK_DGRAM, 0); if (temp_sock == -1) return -1; if (addr->sa_family == AF_INET) { ((struct sockaddr_in*)&tmpaddr)->sin_port = 0; } else { ((struct sockaddr_in6*)&tmpaddr)->sin6_port = 0; } res = bind(temp_sock, &tmpaddr, SA_LEN(&tmpaddr)); serrno = errno; close(temp_sock); if (res == 0) return 0; if (serrno == EADDRNOTAVAIL) return 1; return -1; }
/** Find outbound interface address for a given destination * * Given remote address find local address which the system will use as a source address for sending * datagrams to that remote address. * * @param lia local address. * @param ria the remove address. * @return 0 in success, -1 on failure, address is filled into the first argument. */ int rc_get_srcaddr(struct sockaddr *lia, const struct sockaddr *ria) { int temp_sock; socklen_t namelen; temp_sock = socket(ria->sa_family, SOCK_DGRAM, 0); if (temp_sock == -1) { rc_log(LOG_ERR, "rc_get_srcaddr: socket: %s", strerror(errno)); return -1; } if (connect(temp_sock, ria, SA_LEN(ria)) != 0) { rc_log(LOG_ERR, "rc_get_srcaddr: connect: %s", strerror(errno)); close(temp_sock); return -1; } namelen = SA_LEN(ria); if (getsockname(temp_sock, lia, &namelen) != 0) { rc_log(LOG_ERR, "rc_get_srcaddr: getsockname: %s", strerror(errno)); close(temp_sock); return -1; } close(temp_sock); return 0; }
static struct rtpp_tnotify_target * get_tp4wp(struct rtpp_tnotify_set *pvt, struct rtpp_tnotify_wildcard *wp, struct sockaddr *ccaddr, struct sockaddr *laddr) { int i; struct rtpp_tnotify_target *tp; struct sockaddr_in localhost; if (ccaddr == NULL || ccaddr->sa_family != AF_INET) { /* Request on the unix/IPv6 domain socket, assume it's 127.0.0.1 */ memset(&localhost, '\0', sizeof(struct sockaddr_in)); inet_aton("127.0.0.1", &localhost.sin_addr); ccaddr = sstosa(&localhost); ccaddr->sa_family = AF_INET; } for (i = 0; i < pvt->tp_len; i++) { /* First check against existing targets */ tp = pvt->tp[i]; if (tp->socket_name != NULL) { /* Only match "automatic" entries */ continue; } if (tp->socket_type != wp->socket_type) continue; if (!ishostseq(ccaddr, sstosa(&tp->remote))) continue; if (getport(sstosa(&tp->remote)) != wp->port) continue; return (tp); } /* Nothing found, crank up a new entry */ if (pvt->tp_len == RTPP_TNOTIFY_TARGETS_MAX) { return (NULL); } tp = malloc(sizeof(struct rtpp_tnotify_target)); if (tp == NULL) { return (NULL); } memset(tp, '\0', sizeof(struct rtpp_tnotify_target)); if (laddr != NULL && laddr->sa_family == ccaddr->sa_family) { tp->local = malloc(SA_LEN(laddr)); if (tp->local == NULL) { free(tp); return (NULL); } memcpy(tp->local, laddr, SA_LEN(laddr)); setanyport(tp->local); } tp->remote_len = SA_LEN(ccaddr); memcpy(&tp->remote, ccaddr, tp->remote_len); setport(sstosa(&tp->remote), wp->port); tp->socket_type = wp->socket_type; tp->connected = 0; tp->fd = -1; pvt->tp[pvt->tp_len] = tp; pvt->tp_len += 1; return (tp); }
static int create_twinlistener(struct cfg_stable *cf, struct sockaddr *ia, int port, int *fds) { struct sockaddr_storage iac; int rval, i, flags; fds[0] = fds[1] = -1; rval = -1; for (i = 0; i < 2; i++) { fds[i] = socket(ia->sa_family, SOCK_DGRAM, 0); if (fds[i] == -1) { rtpp_log_ewrite(RTPP_LOG_ERR, cf->glog, "can't create %s socket", (ia->sa_family == AF_INET) ? "IPv4" : "IPv6"); goto failure; } memcpy(&iac, ia, SA_LEN(ia)); satosin(&iac)->sin_port = htons(port); if (bind(fds[i], sstosa(&iac), SA_LEN(ia)) != 0) { if (errno != EADDRINUSE && errno != EACCES) { rtpp_log_ewrite(RTPP_LOG_ERR, cf->glog, "can't bind to the %s port %d", (ia->sa_family == AF_INET) ? "IPv4" : "IPv6", port); } else { rval = -2; } goto failure; } port++; if ((ia->sa_family == AF_INET) && (cf->tos >= 0) && (setsockopt(fds[i], IPPROTO_IP, IP_TOS, &cf->tos, sizeof(cf->tos)) == -1)) rtpp_log_ewrite(RTPP_LOG_ERR, cf->glog, "unable to set TOS to %d", cf->tos); flags = fcntl(fds[i], F_GETFL); fcntl(fds[i], F_SETFL, flags | O_NONBLOCK); } return 0; failure: for (i = 0; i < 2; i++) if (fds[i] != -1) { close(fds[i]); fds[i] = -1; } return rval; }
/* Tear down a connection, can be phase 1 or 2. */ static void ui_teardown(char *cmd) { struct sockaddr_in addr; struct sockaddr_in6 addr6; struct sa *sa; int phase; char name[201]; /* If no phase is given, we default to phase 2. */ phase = 2; if (sscanf(cmd, "t main %200s", name) == 1) phase = 1; else if (sscanf(cmd, "t quick %200s", name) == 1) phase = 2; else if (sscanf(cmd, "t %200s", name) != 1) { log_print("ui_teardown: command \"%s\" malformed", cmd); return; } LOG_DBG((LOG_UI, 10, "ui_teardown: teardown connection \"%s\", " "phase %d", name, phase)); bzero(&addr, sizeof(addr)); bzero(&addr6, sizeof(addr6)); if (inet_pton(AF_INET, name, &addr.sin_addr) == 1) { addr.sin_len = sizeof(addr); addr.sin_family = AF_INET; while ((sa = sa_lookup_by_peer((struct sockaddr *)&addr, SA_LEN((struct sockaddr *)&addr), phase)) != 0) { if (sa->name) connection_teardown(sa->name); sa_delete(sa, 1); } } else if (inet_pton(AF_INET6, name, &addr6.sin6_addr) == 1) { addr6.sin6_len = sizeof(addr6); addr6.sin6_family = AF_INET6; while ((sa = sa_lookup_by_peer((struct sockaddr *)&addr6, SA_LEN((struct sockaddr *)&addr6), phase)) != 0) { if (sa->name) connection_teardown(sa->name); sa_delete(sa, 1); } } else { if (phase == 2) connection_teardown(name); while ((sa = sa_lookup_by_name(name, phase)) != 0) sa_delete(sa, 1); } }
/* * Export a struct sockaddr as an SADB_ADDRESS payload. */ void export_address(void **p, struct sockaddr *sa) { struct sadb_address *sadb_address = (struct sadb_address *) *p; sadb_address->sadb_address_len = (sizeof(struct sadb_address) + PADUP(SA_LEN(sa))) / sizeof(uint64_t); *p += sizeof(struct sadb_address); bcopy(sa, *p, SA_LEN(sa)); ((struct sockaddr *) *p)->sa_family = sa->sa_family; *p += PADUP(SA_LEN(sa)); }
void NET_SendPacket (int length, const void *data, netadr_t to) { int ret; AF_address_t addr; NetadrToSockadr (&to, &addr); ret = sendto (net_socket, data, length, 0, &addr.sa, SA_LEN (&addr.sa)); if (ret == -1) { #ifdef _WIN32 int err = WSAGetLastError (); if (err == WSAEADDRNOTAVAIL) Sys_Printf ("NET_SendPacket Warning: %i\n", err); #else /* _WIN32 */ int err = errno; if (err == ECONNREFUSED) return; #endif /* _WIN32 */ if (err == EWOULDBLOCK) return; Sys_Printf ("NET_SendPacket: %s\n", strerror (err)); } }
static void send_packet(struct cfg *cf, struct rtpp_session *sp, int ridx, struct rtp_packet *packet) { int i, sidx; GET_RTP(sp)->ttl[ridx] = cf->stable.max_ttl; /* Select socket for sending packet out. */ sidx = (ridx == 0) ? 1 : 0; /* * Check that we have some address to which packet is to be * sent out, drop otherwise. */ if (sp->addr[sidx] == NULL || GET_RTP(sp)->rtps[sidx] != NULL) { sp->pcount[3]++; } else { sp->pcount[2]++; for (i = (cf->stable.dmode && packet->size < LBR_THRS) ? 2 : 1; i > 0; i--) { sendto(sp->fds[sidx], packet->data.buf, packet->size, 0, sp->addr[sidx], SA_LEN(sp->addr[sidx])); } } if (sp->rrcs[ridx] != NULL && GET_RTP(sp)->rtps[ridx] == NULL) rwrite(sp, sp->rrcs[ridx], packet); }
int ntp_sendmsg(int fd, struct sockaddr *sa, struct ntp_msg *msg) { socklen_t sa_len; ssize_t n; if (sa != NULL) sa_len = SA_LEN(sa); else sa_len = 0; n = sendto(fd, msg, sizeof(*msg), 0, sa, sa_len); if (n == -1) { if (errno == ENOBUFS || errno == EHOSTUNREACH || errno == ENETDOWN || errno == EHOSTDOWN) { /* logging is futile */ return (-1); } log_warn("sendto"); return (-1); } if (n != sizeof(*msg)) { log_warnx("ntp_sendmsg: only %zd of %zu bytes sent", n, sizeof(*msg)); return (-1); } return (0); }
static int controlfd_init_tcp(struct cfg *cf, struct rtpp_ctrl_sock *csp) { struct sockaddr *ifsin; char *cp; int controlfd, so_rcvbuf, i; cp = strrchr(csp->cmd_sock, ':'); if (cp != NULL) { *cp = '\0'; cp++; } if (cp == NULL || *cp == '\0') cp = CPORT; csp->port_ctl = atoi(cp); i = (csp->type == RTPC_TCP6) ? AF_INET6 : AF_INET; ifsin = sstosa(&csp->bindaddr); if (setbindhost(ifsin, i, csp->cmd_sock, cp) != 0) exit(1); controlfd = socket(i, SOCK_STREAM, 0); if (controlfd == -1) err(1, "can't create socket"); so_rcvbuf = 16 * 1024; if (setsockopt(controlfd, SOL_SOCKET, SO_RCVBUF, &so_rcvbuf, sizeof(so_rcvbuf)) == -1) rtpp_log_ewrite(RTPP_LOG_ERR, cf->stable->glog, "unable to set 16K receive buffer size on controlfd"); if (bind(controlfd, ifsin, SA_LEN(ifsin)) < 0) err(1, "can't bind to a socket"); if (listen(controlfd, 32) != 0) err(1, "can't listen on a socket: %s", csp->cmd_sock); return (controlfd); }
static void test_sa_len(void) { struct sockaddr sa; printf("Test sockaddr_in\n"); sa.sa_family=AF_INET; SET_SA_LEN(&sa, sizeof(struct sockaddr_in)); TEST(SA_LEN(&sa) == sizeof(struct sockaddr_in)); printf("Test sockaddr_in6\n"); sa.sa_family=AF_INET6; SET_SA_LEN(&sa, sizeof(struct sockaddr_in6)); TEST(SA_LEN(&sa) == sizeof(struct sockaddr_in6)); printf("Test sockadd\n"); sa.sa_family=AF_UNSPEC; SET_SA_LEN(&sa, sizeof(struct sockaddr)); TEST(SA_LEN(&sa) == sizeof(struct sockaddr)); }
const char * log_sockaddr(struct sockaddr *sa) { static char buf[NI_MAXHOST]; if (getnameinfo(sa, SA_LEN(sa), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST)) return ("(unknown)"); else return (buf); }
static struct sockaddr * dup_sockaddr(struct sockaddr *sa) { struct sockaddr *newsa; unsigned int size; size = SA_LEN(sa); if ((newsa = malloc(size)) == NULL) return (NULL); return (memcpy(newsa, sa, size)); }
/* * Generate an anti-clogging token (a protection against an attacker forcing * us to keep state for a flood of connection requests) a.k.a. a cookie * at BUF, LEN bytes long. The cookie will be generated by hashing of * information found, among otherplaces, in transport T and exchange * EXCHANGE. */ void cookie_gen(struct transport *t, struct exchange *exchange, u_int8_t *buf, size_t len) { struct hash *hash = hash_get(HASH_SHA1); u_int8_t tmpsecret[COOKIE_SECRET_SIZE]; struct sockaddr *name; hash->Init(hash->ctx); (*t->vtbl->get_dst)(t, &name); hash->Update(hash->ctx, (u_int8_t *)name, SA_LEN(name)); (*t->vtbl->get_src)(t, &name); hash->Update(hash->ctx, (u_int8_t *)name, SA_LEN(name)); if (exchange->initiator == 0) hash->Update(hash->ctx, exchange->cookies + ISAKMP_HDR_ICOOKIE_OFF, ISAKMP_HDR_ICOOKIE_LEN); arc4random_buf(tmpsecret, COOKIE_SECRET_SIZE); hash->Update(hash->ctx, tmpsecret, COOKIE_SECRET_SIZE); hash->Final(hash->digest, hash->ctx); memcpy(buf, hash->digest, len); }
/* * Check if SA matches what we are asking for through V_ARG. It has to * be a finished phase 1 (ISAKMP) SA. */ static int isakmp_sa_check(struct sa *sa, void *v_arg) { struct dst_isakmpspi_arg *arg = v_arg; struct sockaddr *dst, *src; if (sa->phase != 1 || !(sa->flags & SA_FLAG_READY)) return 0; /* verify address is either src or dst for this sa */ sa->transport->vtbl->get_dst(sa->transport, &dst); sa->transport->vtbl->get_src(sa->transport, &src); if (memcmp(src, arg->dst, SA_LEN(src)) && memcmp(dst, arg->dst, SA_LEN(dst))) return 0; /* match icookie+rcookie against spi */ if (memcmp(sa->cookies, arg->spi, ISAKMP_HDR_COOKIES_LEN) == 0) return 1; return 0; }
wi_address_t * wi_address_init_with_sa(wi_address_t *address, struct sockaddr *sa) { if(sa->sa_family != AF_INET && sa->sa_family != AF_INET6) { wi_error_set_error(WI_ERROR_DOMAIN_GAI, EAI_FAMILY); wi_release(address); return NULL; } memcpy(&address->ss, sa, SA_LEN(sa)); return address; }
u_int8_t mask2prefixlen6(struct sockaddr *sa) { struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa; u_int8_t l = 0, *ap, *ep; /* * sin6_len is the size of the sockaddr so substract the offset of * the possibly truncated sin6_addr struct. */ ap = (u_int8_t *)&sa_in6->sin6_addr; ep = (u_int8_t *)sa_in6 + SA_LEN(sa); for (; ap < ep; ap++) { /* this "beauty" is adopted from sbin/route/show.c ... */ switch (*ap) { case 0xff: l += 8; break; case 0xfe: l += 7; return (l); case 0xfc: l += 6; return (l); case 0xf8: l += 5; return (l); case 0xf0: l += 4; return (l); case 0xe0: l += 3; return (l); case 0xc0: l += 2; return (l); case 0x80: l += 1; return (l); case 0x00: return (l); default: return (0); } } return (l); }
static int process_rtp_servers_foreach(void *dp, void *ap) { struct foreach_args *fap; struct rtpp_server *rsrv; struct rtp_packet *pkt; int len; struct rtpp_stream *rsop; uint64_t rtps_old; fap = (struct foreach_args *)ap; /* * This method does not need us to bump ref, since we are in the * locked context of the rtpp_hash_table, which holds its own ref. */ rsrv = (struct rtpp_server *)dp; rsop = CALL_METHOD(fap->rtp_streams_wrt, get_by_idx, rsrv->stuid); if (rsop == NULL) { return (RTPP_WR_MATCH_CONT); } for (;;) { pkt = CALL_METHOD(rsrv, get, fap->dtime, &len); if (pkt == NULL) { if (len == RTPS_EOF) { struct rtpp_stream *rsop_rtcp; CALL_METHOD(rsop, finish_playback, rsrv->sruid); rtps_old = rsrv->sruid; rsop_rtcp = CALL_METHOD(fap->rtcp_streams_wrt, get_by_idx, rsop->stuid_rtcp); if (rsop_rtcp != NULL) { CALL_METHOD(rsop_rtcp, replace_rtps, rtps_old, RTPP_UID_NONE); CALL_METHOD(rsop_rtcp->rcnt, decref); } CALL_METHOD(rsop->rcnt, decref); return (RTPP_WR_MATCH_DEL); } else if (len != RTPS_LATER) { /* XXX some error, brag to logs */ } break; } CALL_METHOD(rsop->fd, send_pkt, fap->sender, rsop->addr, SA_LEN(rsop->addr), pkt, rsop->log); fap->rsp->npkts_played.cnt++; } CALL_METHOD(rsop->rcnt, decref); return (RTPP_WR_MATCH_CONT); }
// this function gets a printable string representing an IP address, given a struct sockaddr pointer. void get_ip_string_and_port(struct sockaddr *paddress, char *ip, int ip_length, int *port) { char *percent; char port_string[MAX_PORT_LENGTH]; // retrieve the ip and port number original_getnameinfo(paddress, SA_LEN(paddress), ip, ip_length, port_string, MAX_PORT_LENGTH, NI_NUMERICHOST|NI_NUMERICSERV); *port = atoi(port_string); // we do not need the scope of the IP // moreover it seems that we get an erroneous scope value when trying to display the scope // of the IPv6 address of a DNS socket (created internally when we call gethostbyname for example). percent = strchr(ip, '%'); if (percent != NULL) { *percent = '\0'; } }
static int UDP_OpenSocket (int port) { int newsocket, i; AF_address_t address; #ifdef _WIN32 #define ioctl ioctlsocket unsigned long flags; #else int flags; #endif memset (&address, 0, sizeof(address)); if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) Sys_Error ("UDP_OpenSocket: socket: %s", strerror (errno)); #if defined (HAVE_IOCTL) || defined (_WIN32) flags = 1; if (ioctl (newsocket, FIONBIO, &flags) == -1) Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror (errno)); #else flags = fcntl(newsocket, F_GETFL, 0); if (fcntl (newsocket, F_SETFL, flags | O_NONBLOCK) == -1) Sys_Error ("UDP_OpenSocket: fcntl O_NONBLOCK: %s", strerror (errno)); #endif address.s4.sin_family = AF_INET; // ZOID -- check for interface binding option if ((i = COM_CheckParm ("-ip")) != 0 && i < com_argc) { address.s4.sin_addr.s_addr = inet_addr (com_argv[i + 1]); Sys_Printf ("Binding to IP Interface Address of %s\n", inet_ntoa (address.s4.sin_addr)); } else address.s4.sin_addr.s_addr = INADDR_ANY; if (port == PORT_ANY) address.s4.sin_port = 0; else address.s4.sin_port = htons ((short) port); if (bind (newsocket, &address.sa, SA_LEN (&address.sa)) == -1) Sys_Error ("UDP_OpenSocket: bind: %s", strerror (errno)); return newsocket; }
/* Check bind */ static int m_priv_check_bind(const struct sockaddr *sa, socklen_t salen) { in_port_t port; if (sa == NULL) { log_print("NULL address"); return 1; } if (SA_LEN(sa) != salen) { log_print("Length mismatch: %lu %lu", (unsigned long)sa->sa_len, (unsigned long)salen); return 1; } switch (sa->sa_family) { case AF_INET: if (salen != sizeof(struct sockaddr_in)) { log_print("Invalid inet address length"); return 1; } port = ((const struct sockaddr_in *)sa)->sin_port; break; case AF_INET6: if (salen != sizeof(struct sockaddr_in6)) { log_print("Invalid inet6 address length"); return 1; } port = ((const struct sockaddr_in6 *)sa)->sin6_port; break; default: log_print("Unknown address family"); return 1; } port = ntohs(port); if (port != ISAKMP_PORT_DEFAULT && port < 1024) { log_print("Disallowed port %u", port); return 1; } return 0; }
static struct rtpp_cmd_connection * rtpp_cmd_connection_ctor(int controlfd_in, int controlfd_out, struct rtpp_ctrl_sock *csock, struct sockaddr *rap) { struct rtpp_cmd_connection *rcc; rcc = malloc(sizeof(struct rtpp_cmd_connection)); if (rcc == NULL) { return (NULL); } memset(rcc, '\0', sizeof(struct rtpp_cmd_connection)); rcc->controlfd_in = controlfd_in; rcc->controlfd_out = controlfd_out; rcc->csock = csock; if (rap != NULL && RTPP_CTRL_ISUNIX(csock) == 0) { rcc->rlen = SA_LEN(rap); memcpy(&rcc->raddr, rap, rcc->rlen); } return (rcc); }
static void process_rtp_servers(struct cfg *cf, double dtime) { int j, k, sidx, len, skipfd; struct rtpp_session *sp; skipfd = 0; for (j = 0; j < cf->rtp_nsessions; j++) { sp = cf->rtp_servers[j]; if (sp == NULL) { skipfd++; continue; } if (skipfd > 0) { cf->rtp_servers[j - skipfd] = cf->rtp_servers[j]; sp->sridx = j - skipfd; } for (sidx = 0; sidx < 2; sidx++) { if (sp->rtps[sidx] == NULL || sp->addr[sidx] == NULL) continue; while ((len = rtp_server_get(sp->rtps[sidx], dtime)) != RTPS_LATER) { if (len == RTPS_EOF) { rtp_server_free(sp->rtps[sidx]); sp->rtps[sidx] = NULL; if (sp->rtps[0] == NULL && sp->rtps[1] == NULL) { assert(cf->rtp_servers[sp->sridx] == sp); cf->rtp_servers[sp->sridx] = NULL; sp->sridx = -1; } break; } for (k = (cf->stable.dmode && len < LBR_THRS) ? 2 : 1; k > 0; k--) { sendto(sp->fds[sidx], sp->rtps[sidx]->buf, len, 0, sp->addr[sidx], SA_LEN(sp->addr[sidx])); } } } } cf->rtp_nsessions -= skipfd; }
static int controlfd_init_udp(struct cfg *cf, struct rtpp_ctrl_sock *csp) { struct sockaddr *ifsin; char *cp; int controlfd, so_rcvbuf, i; cp = strrchr(csp->cmd_sock, ':'); if (cp != NULL) { *cp = '\0'; cp++; } if (cp == NULL || *cp == '\0') cp = CPORT; csp->port_ctl = atoi(cp); i = (csp->type == RTPC_UDP6) ? AF_INET6 : AF_INET; ifsin = sstosa(&csp->bindaddr); if (setbindhost(ifsin, i, csp->cmd_sock, cp) != 0) { warnx("setbindhost failed"); return (-1); } controlfd = socket(i, SOCK_DGRAM, 0); if (controlfd == -1) { warn("can't create socket"); return (-1); } so_rcvbuf = 16 * 1024; if (setsockopt(controlfd, SOL_SOCKET, SO_RCVBUF, &so_rcvbuf, sizeof(so_rcvbuf)) == -1) RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "unable to set 16K receive buffer size on controlfd"); if (bind(controlfd, ifsin, SA_LEN(ifsin)) < 0) { warn("can't bind to a socket"); close(controlfd); return (-1); } return (controlfd); }
static void reconnect_timeout_handler(struct rtpp_log *log, struct rtpp_tnotify_target *rttp) { assert (rttp->connected == 0); if (rttp->fd == -1) { RTPP_LOG(log, RTPP_LOG_DBUG, "connecting timeout socket"); } else { RTPP_LOG(log, RTPP_LOG_DBUG, "reconnecting timeout socket"); close(rttp->fd); } rttp->fd = socket(rttp->socket_type, SOCK_STREAM, 0); if (rttp->fd == -1) { RTPP_ELOG(log, RTPP_LOG_ERR, "can't create timeout socket"); return; } if (rttp->local != NULL) { if (bind(rttp->fd, rttp->local, SA_LEN(rttp->local)) < 0) { RTPP_ELOG(log, RTPP_LOG_ERR, "can't bind timeout socket"); goto e0; } } if (connect(rttp->fd, (struct sockaddr *)&(rttp->remote), rttp->remote_len) == -1) { RTPP_ELOG(log, RTPP_LOG_ERR, "can't connect to timeout socket"); goto e0; } else { rttp->connected = 1; } return; e0: close(rttp->fd); rttp->fd = -1; return; }
/* * Get a list of all interfaces that are up and that we can open. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * could be opened. */ int pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; struct ifaddrs *ifap, *ifa; struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; size_t addr_size, broadaddr_size, dstaddr_size; int ret = 0; char *p, *q; /* * Get the list of interface addresses. * * Note: this won't return information about interfaces * with no addresses, so, if a platform has interfaces * with no interfaces on which traffic can be captured, * we must check for those interfaces as well (see, for * example, what's done on Linux). * * LAN interfaces will probably have link-layer * addresses; I don't know whether all implementations * of "getifaddrs()" now, or in the future, will return * those. */ if (getifaddrs(&ifap) != 0) { (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getifaddrs: %s", pcap_strerror(errno)); return (-1); } for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { /* * "ifa_addr" was apparently null on at least one * interface on some system. Therefore, we supply * the address and netmask only if "ifa_addr" is * non-null (if there's no address, there's obviously * no netmask). */ if (ifa->ifa_addr != NULL) { addr = ifa->ifa_addr; addr_size = SA_LEN(addr); netmask = ifa->ifa_netmask; } else { addr = NULL; addr_size = 0; netmask = NULL; } /* * Note that, on some platforms, ifa_broadaddr and * ifa_dstaddr could be the same field (true on at * least some versions of *BSD and OS X), so we * can't just check whether the broadcast address * is null and add it if so and check whether the * destination address is null and add it if so. * * Therefore, we must also check the IFF_BROADCAST * flag, and only add a broadcast address if it's * set, and check the IFF_POINTTOPOINT flag, and * only add a destination address if it's set (as * per man page recommendations on some of those * platforms). */ if (ifa->ifa_flags & IFF_BROADCAST && ifa->ifa_broadaddr != NULL) { broadaddr = ifa->ifa_broadaddr; broadaddr_size = SA_LEN(broadaddr); } else { broadaddr = NULL; broadaddr_size = 0; } if (ifa->ifa_flags & IFF_POINTOPOINT && ifa->ifa_dstaddr != NULL) { dstaddr = ifa->ifa_dstaddr; dstaddr_size = SA_LEN(ifa->ifa_dstaddr); } else { dstaddr = NULL; dstaddr_size = 0; } /* * If this entry has a colon followed by a number at * the end, we assume it's a logical interface. Those * are just the way you assign multiple IP addresses to * a real interface on Linux, so an entry for a logical * interface should be treated like the entry for the * real interface; we do that by stripping off the ":" * and the number. * * XXX - should we do this only on Linux? */ p = strchr(ifa->ifa_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ q = p + 1; while (isdigit((unsigned char)*q)) q++; if (*q == '\0') { /* * All digits after the ":" until the end. * Strip off the ":" and everything after * it. */ *p = '\0'; } } /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifa->ifa_name, if_flags_to_pcap_flags(ifa->ifa_name, ifa->ifa_flags), addr, addr_size, netmask, addr_size, broadaddr, broadaddr_size, dstaddr, dstaddr_size, errbuf) < 0) { ret = -1; break; } } freeifaddrs(ifap); if (ret == -1) { /* * We had an error; free the list we've been constructing. */ if (devlist != NULL) { pcap_freealldevs(devlist); devlist = NULL; } } *alldevsp = devlist; return (ret); }
int client_query(struct ntp_peer *p) { int val; if (p->addr == NULL && client_nextaddr(p) == -1) { set_next(p, MAX(SETTIME_TIMEOUT, scale_interval(INTERVAL_QUERY_AGGRESSIVE))); return (0); } if (p->state < STATE_DNS_DONE || p->addr == NULL) return (-1); if (p->query->fd == -1) { struct sockaddr *sa = (struct sockaddr *)&p->addr->ss; if ((p->query->fd = socket(p->addr->ss.ss_family, SOCK_DGRAM, 0)) == -1) fatal("client_query socket"); #ifdef HAVE_RTABLE if (p->rtable != -1 && setsockopt(p->query->fd, SOL_SOCKET, SO_RTABLE, &p->rtable, sizeof(p->rtable)) == -1) fatal("client_query setsockopt SO_RTABLE"); #endif if (connect(p->query->fd, sa, SA_LEN(sa)) == -1) { if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EHOSTUNREACH || errno == EADDRNOTAVAIL) { client_nextaddr(p); set_next(p, MAX(SETTIME_TIMEOUT, scale_interval(INTERVAL_QUERY_AGGRESSIVE))); return (-1); } else fatal("client_query connect"); } val = IPTOS_LOWDELAY; if (p->addr->ss.ss_family == AF_INET && setsockopt(p->query->fd, IPPROTO_IP, IP_TOS, &val, sizeof(val)) == -1) log_warn("setsockopt IPTOS_LOWDELAY"); val = 1; if (setsockopt(p->query->fd, SOL_SOCKET, SO_TIMESTAMP, &val, sizeof(val)) == -1) fatal("setsockopt SO_TIMESTAMP"); } /* * Send out a random 64-bit number as our transmit time. The NTP * server will copy said number into the originate field on the * response that it sends us. This is totally legal per the SNTP spec. * * The impact of this is two fold: we no longer send out the current * system time for the world to see (which may aid an attacker), and * it gives us a (not very secure) way of knowing that we're not * getting spoofed by an attacker that can't capture our traffic * but can spoof packets from the NTP server we're communicating with. * * Save the real transmit timestamp locally. */ p->query->msg.xmttime.int_partl = arc4random(); p->query->msg.xmttime.fractionl = arc4random(); p->query->xmttime = gettime_corrected(); if (ntp_sendmsg(p->query->fd, NULL, &p->query->msg) == -1) { p->senderrors++; set_next(p, INTERVAL_QUERY_PATHETIC); p->trustlevel = TRUSTLEVEL_PATHETIC; return (-1); } p->senderrors = 0; p->state = STATE_QUERY_SENT; set_deadline(p, QUERYTIME_MAX); return (0); }
int build_ifclist(int sock, int max, ip_ifc_info * list) { #ifdef _WIN32 int i; int ind; MIB_IPADDRTABLE * info; ULONG out_buf_len; DWORD ret_val; out_buf_len = sizeof *info; info = (MIB_IPADDRTABLE *)loc_alloc(out_buf_len); ret_val = GetIpAddrTable(info, &out_buf_len, 0); if (ret_val == ERROR_INSUFFICIENT_BUFFER) { loc_free(info); info = (MIB_IPADDRTABLE *)loc_alloc(out_buf_len); ret_val = GetIpAddrTable(info, &out_buf_len, 0); } if (ret_val != NO_ERROR) { trace(LOG_ALWAYS, "GetIpAddrTable() error: %d", ret_val); loc_free(info); return 0; } ind = 0; for (i = 0; i < (int)info->dwNumEntries && ind < max; i++) { list[ind].addr = info->table[i].dwAddr; if (list[ind].addr == 0) continue; list[ind].mask = info->table[i].dwMask; ind++; } loc_free(info); #elif defined(__SYMBIAN32__) int ind = 0; ip_ifc_info* info = get_ip_ifc(); if (info) { trace(LOG_ALWAYS,"The IP address is %d.%d.%d.%d", (info->addr >> 24) & 0xff, (info->addr >> 16) & 0xff, (info->addr >> 8) & 0xff, info->addr & 0xff ); list[ind++] = *info; } #else int ind; char * cp; struct ifconf ifc; char if_bbf[0x2000]; memset(&ifc, 0, sizeof ifc); ifc.ifc_len = sizeof if_bbf; ifc.ifc_buf = if_bbf; if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { trace(LOG_ALWAYS, "error: ioctl(SIOCGIFCONF) returned %d: %s", errno, errno_to_str(errno)); return 0; } ind = 0; cp = (char *)ifc.ifc_req; while (cp < (char *)ifc.ifc_req + ifc.ifc_len && ind < max) { struct ifreq * ifreq_addr = (struct ifreq *)cp; struct ifreq ifreq_mask = *ifreq_addr; size_t size = sizeof(struct ifreq); /* BSD systems allow sockaddrs to be longer than their sizeof */ if (SA_LEN(&ifreq_addr->ifr_addr) > sizeof(ifreq_addr->ifr_addr)) size += SA_LEN(&ifreq_addr->ifr_addr) - sizeof(ifreq_addr->ifr_addr); cp += size; if (ifreq_addr->ifr_addr.sa_family != AF_INET) continue; if (ioctl(sock, SIOCGIFNETMASK, &ifreq_mask) < 0) { trace(LOG_ALWAYS, "error: ioctl(SIOCGIFNETMASK) returned %d: %s", errno, errno_to_str(errno)); continue; } list[ind].addr = ((struct sockaddr_in *)&ifreq_addr->ifr_addr)->sin_addr.s_addr; list[ind].mask = ((struct sockaddr_in *)&ifreq_mask.ifr_netmask)->sin_addr.s_addr; ind++; } #endif return ind; }
int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; register int fd; register struct ifreq *ifrp, *ifend, *ifnext; int n; struct ifconf ifc; char *buf = NULL; unsigned buf_size; struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; struct sockaddr *netmask, *broadaddr, *dstaddr; int ret = 0; /* * Create a socket from which to fetch the list of interfaces. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); return (-1); } /* * Start with an 8K buffer, and keep growing the buffer until * we get the entire interface list or fail to get it for some * reason other than EINVAL (which is presumed here to mean * "buffer is too small"). */ buf_size = 8192; for (;;) { buf = malloc(buf_size); if (buf == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); (void)close(fd); return (-1); } ifc.ifc_len = buf_size; ifc.ifc_buf = buf; memset(buf, 0, buf_size); if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 && errno != EINVAL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFCONF: %s", pcap_strerror(errno)); (void)close(fd); free(buf); return (-1); } if (ifc.ifc_len < buf_size) break; free(buf); buf_size *= 2; } ifrp = (struct ifreq *)buf; ifend = (struct ifreq *)(buf + ifc.ifc_len); for (; ifrp < ifend; ifrp = ifnext) { n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name); if (n < sizeof(*ifrp)) ifnext = ifrp + 1; else ifnext = (struct ifreq *)((char *)ifrp + n); /* * Get the flags for this interface, and skip it if it's * not up. */ strncpy(ifrflags.ifr_name, ifrp->ifr_name, sizeof(ifrflags.ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { if (errno == ENXIO) continue; (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS: %.*s: %s", (int)sizeof(ifrflags.ifr_name), ifrflags.ifr_name, pcap_strerror(errno)); ret = -1; break; } if (!(ifrflags.ifr_flags & IFF_UP)) continue; /* * Get the netmask for this address on this interface. */ strncpy(ifrnetmask.ifr_name, ifrp->ifr_name, sizeof(ifrnetmask.ifr_name)); memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr, sizeof(ifrnetmask.ifr_addr)); if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ netmask = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFNETMASK: %.*s: %s", (int)sizeof(ifrnetmask.ifr_name), ifrnetmask.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else netmask = &ifrnetmask.ifr_addr; /* * Get the broadcast address for this address on this * interface (if any). */ if (ifrflags.ifr_flags & IFF_BROADCAST) { strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name, sizeof(ifrbroadaddr.ifr_name)); memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr, sizeof(ifrbroadaddr.ifr_addr)); if (ioctl(fd, SIOCGIFBRDADDR, (char *)&ifrbroadaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ broadaddr = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFBRDADDR: %.*s: %s", (int)sizeof(ifrbroadaddr.ifr_name), ifrbroadaddr.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else broadaddr = &ifrbroadaddr.ifr_broadaddr; } else { /* * Not a broadcast interface, so no broadcast * address. */ broadaddr = NULL; } /* * Get the destination address for this address on this * interface (if any). */ if (ifrflags.ifr_flags & IFF_POINTOPOINT) { strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name, sizeof(ifrdstaddr.ifr_name)); memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr, sizeof(ifrdstaddr.ifr_addr)); if (ioctl(fd, SIOCGIFDSTADDR, (char *)&ifrdstaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ dstaddr = NULL; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFDSTADDR: %.*s: %s", (int)sizeof(ifrdstaddr.ifr_name), ifrdstaddr.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else dstaddr = &ifrdstaddr.ifr_dstaddr; } else dstaddr = NULL; /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifrp->ifr_name, ifrflags.ifr_flags, &ifrp->ifr_addr, netmask, broadaddr, dstaddr, errbuf) < 0) { ret = -1; break; } } free(buf); #ifdef HAVE_PROC_NET_DEV if (ret != -1) { /* * We haven't had any errors yet; now read "/proc/net/dev", * and add to the list of interfaces all interfaces listed * there that we don't already have, because, on Linux, * SIOCGIFCONF reports only interfaces with IPv4 addresses, * so you need to read "/proc/net/dev" to get the names of * the rest of the interfaces. */ ret = scan_proc_net_dev(&devlist, fd, errbuf); } #endif (void)close(fd); if (ret != -1) { /* * We haven't had any errors yet; add the "any" device, * if we can open it. */ if (pcap_add_if(&devlist, "any", 0, any_descr, errbuf) < 0) { /* * Oops, we had a fatal error. */ ret = -1; } } if (ret == -1) { /* * We had an error; free the list we've been constructing. */ if (devlist != NULL) { pcap_freealldevs(devlist); devlist = NULL; } } *alldevsp = devlist; return (ret); }
/* * Get a list of all interfaces that are up and that we can open. * Returns -1 on error, 0 otherwise. * The list, as returned through "alldevsp", may be null if no interfaces * were up and could be opened. * * This is the implementation used on platforms that have SIOCGIFCONF but * don't have any other mechanism for getting a list of interfaces. * * XXX - or platforms that have other, better mechanisms but for which * we don't yet have code to use that mechanism; I think there's a better * way on Linux, for example, but if that better way is "getifaddrs()", * we already have that. */ int pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) { pcap_if_t *devlist = NULL; register int fd; register struct ifreq *ifrp, *ifend, *ifnext; int n; struct ifconf ifc; char *buf = NULL; unsigned buf_size; #if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER) char *p, *q; #endif struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; struct sockaddr *netmask, *broadaddr, *dstaddr; size_t netmask_size, broadaddr_size, dstaddr_size; int ret = 0; /* * Create a socket from which to fetch the list of interfaces. */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); return (-1); } /* * Start with an 8K buffer, and keep growing the buffer until * we have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN" * bytes left over in the buffer or we fail to get the * interface list for some reason other than EINVAL (which is * presumed here to mean "buffer is too small"). */ buf_size = 8192; for (;;) { buf = malloc(buf_size); if (buf == NULL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); (void)close(fd); return (-1); } ifc.ifc_len = buf_size; ifc.ifc_buf = buf; memset(buf, 0, buf_size); if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 && errno != EINVAL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFCONF: %s", pcap_strerror(errno)); (void)close(fd); free(buf); return (-1); } if (ifc.ifc_len < buf_size && (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN) break; free(buf); buf_size *= 2; } ifrp = (struct ifreq *)buf; ifend = (struct ifreq *)(buf + ifc.ifc_len); for (; ifrp < ifend; ifrp = ifnext) { /* * XXX - what if this isn't an IPv4 address? Can * we still get the netmask, etc. with ioctls on * an IPv4 socket? * * The answer is probably platform-dependent, and * if the answer is "no" on more than one platform, * the way you work around it is probably platform- * dependent as well. */ n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name); if (n < sizeof(*ifrp)) ifnext = ifrp + 1; else ifnext = (struct ifreq *)((char *)ifrp + n); /* * XXX - The 32-bit compatibility layer for Linux on IA-64 * is slightly broken. It correctly converts the structures * to and from kernel land from 64 bit to 32 bit but * doesn't update ifc.ifc_len, leaving it larger than the * amount really used. This means we read off the end * of the buffer and encounter an interface with an * "empty" name. Since this is highly unlikely to ever * occur in a valid case we can just finish looking for * interfaces if we see an empty name. */ if (!(*ifrp->ifr_name)) break; /* * Skip entries that begin with "dummy". * XXX - what are these? Is this Linux-specific? * Are there platforms on which we shouldn't do this? */ if (strncmp(ifrp->ifr_name, "dummy", 5) == 0) continue; /* * Get the flags for this interface. */ strncpy(ifrflags.ifr_name, ifrp->ifr_name, sizeof(ifrflags.ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { if (errno == ENXIO) continue; (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS: %.*s: %s", (int)sizeof(ifrflags.ifr_name), ifrflags.ifr_name, pcap_strerror(errno)); ret = -1; break; } /* * Get the netmask for this address on this interface. */ strncpy(ifrnetmask.ifr_name, ifrp->ifr_name, sizeof(ifrnetmask.ifr_name)); memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr, sizeof(ifrnetmask.ifr_addr)); if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ netmask = NULL; netmask_size = 0; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFNETMASK: %.*s: %s", (int)sizeof(ifrnetmask.ifr_name), ifrnetmask.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else { netmask = &ifrnetmask.ifr_addr; netmask_size = SA_LEN(netmask); } /* * Get the broadcast address for this address on this * interface (if any). */ if (ifrflags.ifr_flags & IFF_BROADCAST) { strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name, sizeof(ifrbroadaddr.ifr_name)); memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr, sizeof(ifrbroadaddr.ifr_addr)); if (ioctl(fd, SIOCGIFBRDADDR, (char *)&ifrbroadaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ broadaddr = NULL; broadaddr_size = 0; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFBRDADDR: %.*s: %s", (int)sizeof(ifrbroadaddr.ifr_name), ifrbroadaddr.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else { broadaddr = &ifrbroadaddr.ifr_broadaddr; broadaddr_size = SA_LEN(broadaddr); } } else { /* * Not a broadcast interface, so no broadcast * address. */ broadaddr = NULL; broadaddr_size = 0; } /* * Get the destination address for this address on this * interface (if any). */ if (ifrflags.ifr_flags & IFF_POINTOPOINT) { strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name, sizeof(ifrdstaddr.ifr_name)); memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr, sizeof(ifrdstaddr.ifr_addr)); if (ioctl(fd, SIOCGIFDSTADDR, (char *)&ifrdstaddr) < 0) { if (errno == EADDRNOTAVAIL) { /* * Not available. */ dstaddr = NULL; dstaddr_size = 0; } else { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFDSTADDR: %.*s: %s", (int)sizeof(ifrdstaddr.ifr_name), ifrdstaddr.ifr_name, pcap_strerror(errno)); ret = -1; break; } } else { dstaddr = &ifrdstaddr.ifr_dstaddr; dstaddr_size = SA_LEN(dstaddr); } } else { /* * Not a point-to-point interface, so no destination * address. */ dstaddr = NULL; dstaddr_size = 0; } #if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER) /* * If this entry has a colon followed by a number at * the end, it's a logical interface. Those are just * the way you assign multiple IP addresses to a real * interface, so an entry for a logical interface should * be treated like the entry for the real interface; * we do that by stripping off the ":" and the number. */ p = strchr(ifrp->ifr_name, ':'); if (p != NULL) { /* * We have a ":"; is it followed by a number? */ q = p + 1; while (isdigit((unsigned char)*q)) q++; if (*q == '\0') { /* * All digits after the ":" until the end. * Strip off the ":" and everything after * it. */ *p = '\0'; } } #endif /* * Add information for this address to the list. */ if (add_addr_to_iflist(&devlist, ifrp->ifr_name, ifrflags.ifr_flags, &ifrp->ifr_addr, SA_LEN(&ifrp->ifr_addr), netmask, netmask_size, broadaddr, broadaddr_size, dstaddr, dstaddr_size, errbuf) < 0) { ret = -1; break; } } free(buf); (void)close(fd); if (ret == -1) { /* * We had an error; free the list we've been constructing. */ if (devlist != NULL) { pcap_freealldevs(devlist); devlist = NULL; } } *alldevsp = devlist; return (ret); }