コード例 #1
0
/** 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;
}
コード例 #2
0
ファイル: ip_util.c プロジェクト: credil/radcli
/** 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;
}
コード例 #3
0
ファイル: rtpp_tnotify_set.c プロジェクト: Marhbere/rtpproxy
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);
}
コード例 #4
0
ファイル: rtpp_command.c プロジェクト: sambatyon/rtpproxy
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;
}
コード例 #5
0
ファイル: ui.c プロジェクト: SylvestreG/bitrig
/* 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);
	}
}
コード例 #6
0
ファイル: pfkeyv2_convert.c プロジェクト: MarginC/kame
/*
 * 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));
}
コード例 #7
0
ファイル: net_udp.c プロジェクト: EIREXE/Quakeforge-gcw0
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));
	}
}
コード例 #8
0
ファイル: main.c プロジェクト: DrumTechnologiesLtd/rtpproxy
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);
}
コード例 #9
0
ファイル: ntp_msg.c プロジェクト: github188/SimpleCode
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);
}
コード例 #10
0
ファイル: rtpp_controlfd.c プロジェクト: Marhbere/rtpproxy
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);
}
コード例 #11
0
ファイル: test_gateway.c プロジェクト: SysMan-One/pcp
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));
}
コード例 #12
0
ファイル: log.c プロジェクト: acassis/emlinux-ssd1935
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);
}
コード例 #13
0
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));
}
コード例 #14
0
ファイル: cookie.c プロジェクト: SylvestreG/bitrig
/*
 * 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);
}
コード例 #15
0
ファイル: sa.c プロジェクト: repos-holder/openbsd-patches
/*
 * 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;
}
コード例 #16
0
ファイル: wi-address.c プロジェクト: Patater/libwired
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;
}
コード例 #17
0
ファイル: util.c プロジェクト: artasoftkey/openiked
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);
}
コード例 #18
0
ファイル: rtpp_proc_servers.c プロジェクト: kcratie/rtpproxy
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);
}
コード例 #19
0
// 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';
    }
}
コード例 #20
0
ファイル: net_udp.c プロジェクト: EIREXE/Quakeforge-gcw0
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;
}
コード例 #21
0
ファイル: monitor.c プロジェクト: mohammadhamad/mhhgen
/* 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;
}
コード例 #22
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);
}
コード例 #23
0
ファイル: main.c プロジェクト: DrumTechnologiesLtd/rtpproxy
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;
}
コード例 #24
0
ファイル: rtpp_controlfd.c プロジェクト: sippy/rtpproxy
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);
}
コード例 #25
0
ファイル: rtpp_notify.c プロジェクト: digideskio/rtpproxy
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;
}
コード例 #26
0
ファイル: fad-getad.c プロジェクト: 12sidedtech/libpcap
/*
 * 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);
}
コード例 #27
0
ファイル: client.c プロジェクト: clongeau/openntpd
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);
}
コード例 #28
0
ファイル: ip_ifc.c プロジェクト: wind-river-cdt/tcf.agent
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;
}
コード例 #29
0
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);
}
コード例 #30
0
ファイル: fad-gifc.c プロジェクト: 0225kazuki/packet_capture
/*
 * 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);
}