예제 #1
0
/*
 - ttosubnet - convert text "addr/mask" to address and mask
 * Mask can be integer bit count.
 */
err_t
ttosubnet(const char *src, size_t srclen,int af,ip_subnet *dst)
{
	const char *slash;
	const char *colon;
	const char *mask;
	size_t mlen;
	const char *oops;
	unsigned long bc;
	static char def[] = DEFAULTSUBNET;
#	define	DEFLEN	(sizeof(def) - 1)	/* -1 for NUL */
	static char defis4[] = "0/0";
#	define	DEFIS4LEN	(sizeof(defis4) - 1)
	static char defis6[] = "::/0";
#	define	DEFIS6LEN	(sizeof(defis6) - 1)
	ip_address addrtmp;
	ip_address masktmp;
	int nbits;
	int i;

	if (srclen == 0)
		srclen = strlen(src);
	if (srclen == 0)
		return "empty string";

	switch (af) {
	case AF_INET:
		nbits = 32;
		break;
	case AF_INET6:
		nbits = 128;
		break;
	default:
		return "unknown address family in ttosubnet";
		break;
	}

	if (srclen == DEFLEN && strncmp(src, def, srclen) == 0) {
		src = (af == AF_INET) ? defis4 : defis6;
		srclen = (af == AF_INET) ? DEFIS4LEN : DEFIS6LEN;
	}

	slash = memchr(src, '/', srclen);
	if (slash == NULL)
		return "no / in subnet specification";
	mask = slash + 1;
	mlen = srclen - (mask - src);
	oops = ttoaddr(src, slash-src, af, &addrtmp);
	if (oops != NULL)
		return oops;

	/* extract port, as last : */
	colon = memchr(mask, ':', mlen);
	if (colon == 0)
	{
		setportof(0, &addrtmp);
	}
	else
	{
		unsigned long port;

		oops =  ttoul(colon+1, mlen-(colon-mask+1), 0, &port);
		if (oops != NULL)
			return oops;
		setportof(htons(port), &addrtmp);
		mlen = colon - mask;
	}

	/*extract mask */
	oops = ttoul(mask, mlen, 10, &bc);
	if (oops == NULL) {
		/* ttoul succeeded, it's a bit-count mask */
		if (bc > nbits)
			return "subnet mask bit count too large";
		i = bc;
	} else if(af == AF_INET) {
		oops = ttoaddr(mask, mlen, af, &masktmp);
		if (oops != NULL)
			return oops;
		i = masktocount(&masktmp);
		if (i < 0)
			return "non-contiguous or otherwise erroneous mask";
	} else {
	  return "masks are not permitted for IPv6 addresses";
	}
	return initsubnet(&addrtmp, i, '0', dst);
}
예제 #2
0
void recv_pcap_packet_gen(u_char *user,
			  const struct pcap_pkthdr *h,
			  const u_char *bytes)
{
	struct msg_digest *md;
	u_int32_t *dlt;
	struct iphdr  *ip;
	struct udphdr *udp;
	u_char    *ike;
	const struct iface_port *ifp = &if1;
	int packet_len;
	err_t from_ugh;

	union {
		struct sockaddr sa;
		struct sockaddr_in sa_in4;
		struct sockaddr_in6 sa_in6;
	} from;

	md = alloc_md();
	dlt = (u_int32_t *)bytes;
	if (*dlt != PF_INET)
		return;

	ip  = (struct iphdr *)(dlt + 1);
	udp = (struct udphdr *)(dlt + ip->ihl + 1);
	ike = (u_char *)(udp + 1);

	from.sa_in4.sin_addr.s_addr = ip->saddr;
	from.sa_in4.sin_port        = udp->source;

	md->iface = ifp;
	packet_len = h->len - (ike - bytes);

	happy(anyaddr(addrtypeof(&ifp->ip_addr), &md->sender));

	from_ugh = initaddr((void *) &from.sa_in4.sin_addr,
			    sizeof(from.sa_in4.sin_addr),
			    AF_INET, &md->sender);
	setportof(from.sa_in4.sin_port, &md->sender);
	md->sender_port = ntohs(from.sa_in4.sin_port);

	cur_from      = &md->sender;
	cur_from_port = md->sender_port;

	/* Clone actual message contents
	 * and set up md->packet_pbs to describe it.
	 */
	init_pbs(&md->packet_pbs,
		 clone_bytes(ike, packet_len,
			     "message buffer in comm_handle()"),
		 packet_len, "packet");

	DBG_log("*received %d bytes from %s:%u on %s (port=%d)",
		(int) pbs_room(&md->packet_pbs),
		ip_str(&md->sender), (unsigned) md->sender_port,
		ifp->ip_dev->id_rname,
		ifp->port);

	DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs));

	process_packet(&md);

	if (md != NULL)
		release_md(md);

	cur_state = NULL;
	reset_cur_connection();
	cur_from = NULL;
}
예제 #3
0
struct raw_iface *
find_raw_ifaces4(void)
{
    static const int on = TRUE;	/* by-reference parameter; constant, we hope */
    int j;	/* index into buf */
    static int    num=64;    /* number of interfaces */
    struct ifconf ifconf;
    struct ifreq *buf;	     /* for list of interfaces -- arbitrary limit */
    struct raw_iface *rifaces = NULL;
    int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);    /* Get a UDP socket */

    /* get list of interfaces with assigned IPv4 addresses from system */

    if (master_sock == -1)
	exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));

    if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR
		   , (const void *)&on, sizeof(on)) < 0)
	    exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));

    /* bind the socket */
    {
	ip_address any;

	happy(anyaddr(AF_INET, &any));
	setportof(htons(pluto_port), &any);
	if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0)
	    exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));
    }

    buf = NULL;
   
    /* a million interfaces is probably the maximum, ever... */
    while(num < (1024*1024)) {
	    /* Get local interfaces.  See netdevice(7). */
	    ifconf.ifc_len = num * sizeof(struct ifreq);
	    buf = (void *) realloc(buf, ifconf.ifc_len);
	    if (!buf)
		    exit_log_errno((e, "realloc of %d in find_raw_ifaces4()",
				    ifconf.ifc_len));
	    memset(buf, 0, num*sizeof(struct ifreq));
	    ifconf.ifc_buf = (void *) buf;
	    
	    if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
		    exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
	    
	    /* if we got back less than we asked for, we have them all */
	    if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num))
		    break;
	    
	    /* try again and ask for more this time */
	    num *= 2;
    }
  
    /* Add an entry to rifaces for each interesting interface. */
    for (j = 0; (j+1) * sizeof(struct ifreq) <= (size_t)ifconf.ifc_len; j++)
    {
	struct raw_iface ri;
	const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;
	struct ifreq auxinfo;

	/* ignore all but AF_INET interfaces */
	if (rs->sin_family != AF_INET)
	    continue;	/* not interesting */

	/* build a NUL-terminated copy of the rname field */
	memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ);
	ri.name[IFNAMSIZ] = '\0';

	/* ignore if our interface names were specified, and this isn't one */
	if (pluto_ifn_roof != 0)
	{
	    int i;

	    for (i = 0; i != pluto_ifn_roof; i++)
		if (streq(ri.name, pluto_ifn[i]))
		    break;
	    if (i == pluto_ifn_roof)
		continue;	/* not found -- skip */
	}

	/* Find out stuff about this interface.  See netdevice(7). */
	zero(&auxinfo);	/* paranoia */
	memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ);
	if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1)
	    exit_log_errno((e
		, "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()"
		, ri.name));
	if (!(auxinfo.ifr_flags & IFF_UP))
	   {
		DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is not up"
	    , ri.name));
	    continue;	/* ignore an interface that isn't UP */
	   }
        if (auxinfo.ifr_flags & IFF_SLAVE)
	   {
		DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is a slave interface"
	    , ri.name));
            continue;   /* ignore slave interfaces; they share IPs with their master */
	   }

	/* ignore unconfigured interfaces */
	if (rs->sin_addr.s_addr == 0)
	   {
		DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is unconfigured"
	    , ri.name));
	    continue;
	   }

	happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr)
	    , AF_INET, &ri.addr));

	DBG(DBG_CONTROL, DBG_log("found %s with address %s"
	    , ri.name, ip_str(&ri.addr)));
	ri.next = rifaces;
	rifaces = clone_thing(ri, "struct raw_iface");
    }

    close(master_sock);

    return rifaces;
}
예제 #4
0
static void
bsdkame_process_raw_ifaces(struct raw_iface *rifaces)
{
    struct raw_iface *ifp;

    /* 
     * There are no virtual interfaces, so all interfaces are valid
     */
    for (ifp = rifaces; ifp != NULL; ifp = ifp->next)
    {
	bool after = FALSE; /* has vfp passed ifp on the list? */
	bool bad = FALSE;
	struct raw_iface *vfp;

	for (vfp = rifaces; vfp != NULL; vfp = vfp->next)
	{
	    if (vfp == ifp)
	    {
		after = TRUE;
	    }
	    else if (sameaddr(&ifp->addr, &vfp->addr))
	    {
	      if (after)
		{
		  loglog(RC_LOG_SERIOUS
			 , "IP interfaces %s and %s share address %s!"
			 , ifp->name, vfp->name, ip_str(&ifp->addr));
		}
	      bad = TRUE;
	    }
	}

	if (bad)
	    continue;

	/* We've got all we need; see if this is a new thing:
	 * search old interfaces list.
	 */
	{
	    struct iface_port **p = &interfaces;

	    for (;;)
	    {
		struct iface_port *q = *p;
		struct iface_dev *id = NULL;

		/* search is over if at end of list */
		if (q == NULL)
		{
		    /* matches nothing -- create a new entry */
		    int fd = create_socket(ifp, ifp->name, pluto_port);

		    if (fd < 0)
			break;

#ifdef NAT_TRAVERSAL
		    if (nat_traversal_support_non_ike && addrtypeof(&ifp->addr) == AF_INET)
		    {
			nat_traversal_espinudp_socket(fd, "IPv4", ESPINUDP_WITH_NON_IKE);
		    }
#endif

		    q = alloc_thing(struct iface_port, "struct iface_port");
		    id = alloc_thing(struct iface_dev, "struct iface_dev");

		    LIST_INSERT_HEAD(&interface_dev, id, id_entry);

		    q->ip_dev = id;
		    id->id_rname = clone_str(ifp->name, "real device name");
		    id->id_vname = clone_str(ifp->name, "virtual device name");
		    id->id_count++;

		    q->ip_addr = ifp->addr;
		    q->fd = fd;
		    q->next = interfaces;
		    q->change = IFN_ADD;
		    q->port = pluto_port;
		    q->ike_float = FALSE;

		    interfaces = q;

		    openswan_log("adding interface %s/%s %s:%d"
				 , q->ip_dev->id_vname
				 , q->ip_dev->id_rname
				 , ip_str(&q->ip_addr)
				 , q->port);

#ifdef NAT_TRAVERSAL
		    /*
		     * right now, we do not support NAT-T on IPv6, because
		     * the kernel did not support it, and gave an error
		     * it one tried to turn it on.
		     */
		    if (nat_traversal_support_port_floating
			&& addrtypeof(&ifp->addr) == AF_INET)
		    {
			fd = create_socket(ifp, id->id_vname, NAT_T_IKE_FLOAT_PORT);
			if (fd < 0) 
			    break;
			nat_traversal_espinudp_socket(fd, "IPv4"
						      , ESPINUDP_WITH_NON_ESP);
			q = alloc_thing(struct iface_port, "struct iface_port");
			q->ip_dev = id;
			id->id_count++;
			
			q->ip_addr = ifp->addr;
			setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->ip_addr);
			q->port = NAT_T_IKE_FLOAT_PORT;
			q->fd = fd;
			q->next = interfaces;
			q->change = IFN_ADD;
			q->ike_float = TRUE;
			interfaces = q;
			openswan_log("adding interface %s/%s %s:%d"
				     , q->ip_dev->id_vname, q->ip_dev->id_rname
				     , ip_str(&q->ip_addr)
				     , q->port);
		    }
#endif
		    break;
		}

		/* search over if matching old entry found */
		if (streq(q->ip_dev->id_rname, ifp->name)
		    && streq(q->ip_dev->id_vname, ifp->name)
		    && sameaddr(&q->ip_addr, &ifp->addr))
		{
		    /* matches -- rejuvinate old entry */
		    q->change = IFN_KEEP;
#ifdef NAT_TRAVERSAL
		    /* look for other interfaces to keep (due to NAT-T) */
		    for (q = q->next ; q ; q = q->next) {
			if (streq(q->ip_dev->id_rname, ifp->name)
			    && streq(q->ip_dev->id_vname, ifp->name)
			    && sameaddr(&q->ip_addr, &ifp->addr)) {
				q->change = IFN_KEEP;
			}
		    }
#endif
		    break;
		}

		/* try again */
		p = &q->next;
	    } /* for (;;) */
	}
예제 #5
0
static void klips_process_raw_ifaces(struct raw_iface *rifaces)
{
	struct raw_iface *ifp;

	/* Find all virtual/real interface pairs.
	 * For each real interface...
	 */
	for (ifp = rifaces; ifp != NULL; ifp = ifp->next) {
		struct raw_iface *v = NULL;     /* matching ipsecX interface */
		struct raw_iface fake_v;
		bool after = FALSE;             /* has vfp passed ifp on the list? */
		bool bad = FALSE;
		struct raw_iface *vfp;
		ip_address lip;

		if (pluto_listen) {
			err_t e;
			e = ttoaddr(pluto_listen, 0, 0, &lip);
			if (e) {
				DBG_log("invalid listen= option ignored: %s\n",
					e);
				pluto_listen = NULL;
			}
		}

		/* ignore if virtual (ipsec*) interface */
		if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX) -
			    1) == 0)
			continue;

		/* ignore if virtual (mast*) interface */
		if (strncmp(ifp->name, MASTDEVPREFIX, sizeof(MASTDEVPREFIX) -
			    1) == 0)
			continue;

		for (vfp = rifaces; vfp != NULL; vfp = vfp->next) {
			if (vfp == ifp) {
				after = TRUE;
			} else if (sameaddr(&ifp->addr, &vfp->addr)) {
				/* Different entries with matching IP addresses.
				 * Many interesting cases.
				 */
				if (strncmp(vfp->name, IPSECDEVPREFIX,
					    sizeof(IPSECDEVPREFIX) - 1) == 0) {
					if (v != NULL) {
						loglog(RC_LOG_SERIOUS,
						       "ipsec interfaces %s and %s share same address %s",
						       v->name, vfp->name,
						       ip_str(&ifp->addr));
						bad = TRUE;
					} else {
						v = vfp; /* current winner */
					}
				} else {
					/* ugh: a second real interface with the same IP address
					 * "after" allows us to avoid double reporting.
					 */
#if defined(linux) && defined(NETKEY_SUPPORT)
					if (kern_interface == USE_NETKEY) {
						if (after) {
							bad = TRUE;
							break;
						}
						continue;
					}
#endif
					if (after) {
						loglog(RC_LOG_SERIOUS,
						       "IP interfaces %s and %s share address %s!",
						       ifp->name, vfp->name,
						       ip_str(&ifp->addr));
					}
					bad = TRUE;
				}
			}
		}

		if (bad)
			continue;

#if defined(linux) && defined(NETKEY_SUPPORT)
		if (kern_interface == USE_NETKEY) {
			v = ifp;
			goto add_entry;
		}
#endif

		/* what if we didn't find a virtual interface? */
		if (v == NULL) {
			if (kern_interface == NO_KERNEL) {
				/* kludge for testing: invent a virtual device */
				static const char fvp[] = "virtual";
				fake_v = *ifp;
				passert(sizeof(fake_v.name) > sizeof(fvp));
				strcpy(fake_v.name, fvp);
				addrtot(&ifp->addr, 0,
					fake_v.name + sizeof(fvp) - 1,
					sizeof(fake_v.name) -
					(sizeof(fvp) - 1));
				v = &fake_v;
			} else {
				DBG(DBG_CONTROL,
				    DBG_log(
					    "IP interface %s %s has no matching ipsec* interface -- ignored",
					    ifp->name, ip_str(&ifp->addr)));
				continue;
			}
		}

		/* ignore if --listen is specified and we do not match */
		if (pluto_listen != NULL) {
			if (!sameaddr(&lip, &ifp->addr)) {
				libreswan_log("skipping interface %s with %s",
					      ifp->name, ip_str(&ifp->addr));
				continue;
			}
		}

		/* We've got all we need; see if this is a new thing:
		 * search old interfaces list.
		 */
#if defined(linux) && defined(NETKEY_SUPPORT)
add_entry:
#endif
		{
			struct iface_port **p = &interfaces;

			for (;; ) {
				struct iface_port *q = *p;
				struct iface_dev *id = NULL;

				/* search is over if at end of list */
				if (q == NULL) {
					/* matches nothing -- create a new entry */
					int fd = create_socket(ifp, v->name,
							       pluto_port);

					if (fd < 0)
						break;

					DBG(DBG_NATT,
					    DBG_log(
						    "NAT-T KLIPS: checking for nat_traversal_support_non_ike for IPv4"));
					if (nat_traversal_support_non_ike &&
					    addrtypeof(&ifp->addr) ==
					    AF_INET) {
						DBG(DBG_NATT,
						    DBG_log(
							    "NAT-T KLIPS: found, calling nat_traversal_espinudp_socket"));
						nat_traversal_espinudp_socket(
							fd, "IPv4",
							ESPINUDP_WITH_NON_IKE);
					} else {
						DBG(DBG_NATT,
						    DBG_log(
							    "NAT-T KLIPS: support not found, nat_traversal_support_non_ike = %s",
							    nat_traversal_support_non_ike
							    ?
							    "TRUE" : "FALSE"));
					}

					q = alloc_thing(struct iface_port,
							"struct iface_port");
					id = alloc_thing(struct iface_dev,
							 "struct iface_dev");

					LIST_INSERT_HEAD(&interface_dev, id,
							 id_entry);

					q->ip_dev = id;
					id->id_rname = clone_str(ifp->name,
								 "real device name");
					id->id_vname = clone_str(v->name,
								 "virtual device name klips");
					id->id_count++;

					q->ip_addr = ifp->addr;
					q->fd = fd;
					q->next = interfaces;
					q->change = IFN_ADD;
					q->port = pluto_port;
					q->ike_float = FALSE;

					interfaces = q;

					libreswan_log(
						"adding interface %s/%s %s:%d",
						q->ip_dev->id_vname,
						q->ip_dev->id_rname,
						ip_str(&q->ip_addr),
						q->port);

					/*
					 * right now, we do not support NAT-T on IPv6, because
					 * the kernel did not support it, and gave an error
					 * it one tried to turn it on.
					 */
					if (nat_traversal_support_port_floating
					    &&
					    addrtypeof(&ifp->addr) ==
					    AF_INET) {
						DBG(DBG_NATT,
						    DBG_log(
							    "NAT-T KLIPS: found floating port, calling nat_traversal_espinudp_socket"));
						fd = create_socket(ifp,
								   v->name,
								   pluto_natt_float_port);
						if (fd < 0)
							break;
						nat_traversal_espinudp_socket(
							fd, "IPv4",
							ESPINUDP_WITH_NON_ESP);
						q = alloc_thing(
							struct iface_port,
							"struct iface_port");
						q->ip_dev = id;
						id->id_count++;

						q->ip_addr = ifp->addr;
						setportof(htons(
								  pluto_natt_float_port),
							  &q->ip_addr);
						q->port =
							pluto_natt_float_port;
						q->fd = fd;
						q->next = interfaces;
						q->change = IFN_ADD;
						q->ike_float = TRUE;
						interfaces = q;
						libreswan_log(
							"adding interface %s/%s %s:%d",
							q->ip_dev->id_vname, q->ip_dev->id_rname,
							ip_str(&q->
							       ip_addr),
							q->port);
					}
					break;
				}

				/* search over if matching old entry found */
				if (streq(q->ip_dev->id_rname, ifp->name) &&
				    streq(q->ip_dev->id_vname, v->name) &&
				    sameaddr(&q->ip_addr, &ifp->addr)) {
					/* matches -- rejuvinate old entry */
					q->change = IFN_KEEP;

					/* look for other interfaces to keep (due to NAT-T) */
					for (q = q->next; q; q = q->next) {
						if (streq(q->ip_dev->id_rname,
							  ifp->name) &&
						    streq(q->ip_dev->id_vname,
							  v->name) &&
						    sameaddr(&q->ip_addr,
							     &ifp->addr))
							q->change = IFN_KEEP;
					}

					break;
				}

				/* try again */
				p = &q->next;
			} /* for (;;) */
		}
예제 #6
0
struct raw_iface *find_raw_ifaces4(void)
{
	static const int on = TRUE;	/* by-reference parameter; constant, we hope */
	int j;	/* index into buf */
	struct ifconf ifconf;
	struct ifreq *buf = NULL;	/* for list of interfaces -- arbitrary limit */
	struct ifreq *bp;	/* cursor into buf */
	struct raw_iface *rifaces = NULL;
	int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);        /* Get a UDP socket */

	/*
	 * Current upper bound on number of interfaces.
	 * Tricky: because this is a static, we won't have to start from
	 * 64 in subsequent calls.
	 */
	static int num = 64;	/* number of interfaces */

	/* get list of interfaces with assigned IPv4 addresses from system */

	if (master_sock == -1)
		exit_log_errno((e, "socket() failed in find_raw_ifaces4()"));

	if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR,
		       (const void *)&on, sizeof(on)) < 0)
		exit_log_errno((e, "setsockopt() in find_raw_ifaces4()"));

	/* bind the socket */
	{
		ip_address any;

		happy(anyaddr(AF_INET, &any));
		setportof(htons(pluto_port), &any);
		if (bind(master_sock, sockaddrof(&any),
			 sockaddrlenof(&any)) < 0)
			exit_log_errno((e,
					"bind() failed in find_raw_ifaces4()"));
	}

	/* a million interfaces is probably the maximum, ever... */
	for (; num < (1024 * 1024); num *= 2) {
		/* Get num local interfaces.  See netdevice(7). */
		ifconf.ifc_len = num * sizeof(struct ifreq);
		buf = realloc(buf, ifconf.ifc_len);
		if (buf == NULL) {
			exit_log_errno((e,
					"realloc of %d in find_raw_ifaces4()",
					ifconf.ifc_len));
		}
		memset(buf, 0xDF, ifconf.ifc_len);	/* stomp */
		ifconf.ifc_buf = (void *) buf;

		if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
			exit_log_errno((e,
					"ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));


		/* if we got back less than we asked for, we have them all */
		if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num))
			break;
	}

	/* Add an entry to rifaces for each interesting interface.
	   On Apple, the size of struct ifreq depends on the contents of
	   the union. See if.h */
	for (bp = buf, j = 0;
	     bp < (unsigned char *)buf + (size_t)ifconf.ifc_len;
	     bp = (struct ifreq *)
		((unsigned char *)bp +_SIZEOF_ADDR_IFREQ(*bp)),
	     j++) {
		struct raw_iface ri;
		const struct sockaddr_in *rs =
			(struct sockaddr_in *) &bp->ifr_addr;
		struct ifreq auxinfo;

		/* ignore all but AF_INET interfaces */
		if (rs->sin_family != AF_INET)
			continue; /* not interesting */

		/* build a NUL-terminated copy of the rname field */
		memcpy(ri.name, bp->ifr_name, IFNAMSIZ);
		ri.name[IFNAMSIZ] = '\0';

		/* ignore if our interface names were specified, and this isn't one */
		if (pluto_ifn_roof != 0) {
			int i;

			for (i = 0; i != pluto_ifn_roof; i++)
				if (streq(ri.name, pluto_ifn[i]))
					break;
			if (i == pluto_ifn_roof)
				continue; /* not found -- skip */
		}

		/* Find out stuff about this interface.  See netdevice(7). */
		zero(&auxinfo); /* paranoia */
		memcpy(auxinfo.ifr_name, bp->ifr_name, IFNAMSIZ);
		if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) {
			exit_log_errno((e,
					"ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()",
					ri.name));
		}
		if (!(auxinfo.ifr_flags & IFF_UP))
			continue; /* ignore an interface that isn't UP */

		/* ignore unconfigured interfaces */
		if (rs->sin_addr.s_addr == 0)
			continue;

		happy(initaddr((const void *)&rs->sin_addr,
			       sizeof(struct in_addr),
			       AF_INET, &ri.addr));

		DBG(DBG_CONTROL, {
			ipstr_buf b;
			DBG_log("found %s with address %s",
				ri.name, ipstr(&ri.addr, &b));
		});
		ri.next = rifaces;
		rifaces = clone_thing(ri, "struct raw_iface");
	}