Ejemplo n.º 1
0
		 , unsigned int proto UNUSED
		 , unsigned int transport_proto
		 , unsigned int satype
		 , const struct pfkey_proto_info *proto_info UNUSED
		 , time_t use_lifetime UNUSED
		 , unsigned int op
		 , const char *text_said)
{
    struct sadb_ext *extensions[SADB_EXT_MAX + 1];
    ip_address
	sflow_ska,
	dflow_ska,
	smask_ska,
	dmask_ska;

    int sport = ntohs(portof(&this_client->addr));
    int dport = ntohs(portof(&that_client->addr));

    networkof(this_client, &sflow_ska);
    maskof(this_client, &smask_ska);
    setportof(sport ? ~0:0, &smask_ska);

    networkof(that_client, &dflow_ska);
    maskof(that_client, &dmask_ska);
    setportof(dport ? ~0:0, &dmask_ska);

    if (!pfkey_msg_start(op & ERO_MASK, satype
		       , "pfkey_msg_hdr flow", text_said, extensions))
    {
	return FALSE;
    }
Ejemplo n.º 2
0
/** netlink_raw_eroute
 *
 * @param this_host ip_address
 * @param this_client ip_subnet
 * @param that_host ip_address
 * @param that_client ip_subnet
 * @param spi
 * @param proto int (Currently unused) Contains protocol (u=tcp, 17=udp, etc...)
 * @param transport_proto int (Currently unused) 0=tunnel, 1=transport
 * @param satype int
 * @param proto_info 
 * @param lifetime (Currently unused)
 * @param ip int 
 * @return boolean True if successful 
 */
static bool
netlink_raw_eroute(const ip_address *this_host
		   , const ip_subnet *this_client
		   , const ip_address *that_host
		   , const ip_subnet *that_client
		   , ipsec_spi_t spi
		   , unsigned int proto UNUSED
		   , unsigned int transport_proto UNUSED
		   , unsigned int satype
		   , const struct pfkey_proto_info *proto_info
		   , time_t use_lifetime UNUSED
		   , unsigned int op
		   , const char *text_said)
{
    struct {
	struct nlmsghdr n;
	union {
	    struct xfrm_userpolicy_info p;
	    struct xfrm_userpolicy_id id;
	} u;
	char data[1024];
    } req;
    int shift;
    int dir;
    int family;
    int policy;
    bool ok;
    bool enoent_ok;

    policy = IPSEC_POLICY_IPSEC;

    if (satype == SADB_X_SATYPE_INT)
    {
	/* shunt route */
	switch (ntohl(spi))
	{
	case SPI_PASS:
	    policy = IPSEC_POLICY_NONE;
	    break;
	case SPI_DROP:
	case SPI_REJECT:
	default:
	    policy = IPSEC_POLICY_DISCARD;
	    break;
	case SPI_TRAP:
	case SPI_TRAPSUBNET:
	case SPI_HOLD:
	    if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
	    {
		return TRUE;
	    }
	    break;
	}
    }

    memset(&req, 0, sizeof(req));
    req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;

    family = that_client->addr.u.v4.sin_family;
    shift = (family == AF_INET) ? 5 : 7;

    req.u.p.sel.sport = portof(&this_client->addr);
    req.u.p.sel.dport = portof(&that_client->addr);
    req.u.p.sel.sport_mask = (req.u.p.sel.sport) ? ~0:0;
    req.u.p.sel.dport_mask = (req.u.p.sel.dport) ? ~0:0;
    ip2xfrm(&this_client->addr, &req.u.p.sel.saddr);
    ip2xfrm(&that_client->addr, &req.u.p.sel.daddr);
    req.u.p.sel.prefixlen_s = this_client->maskbits;
    req.u.p.sel.prefixlen_d = that_client->maskbits;
    req.u.p.sel.proto = transport_proto;
    req.u.p.sel.family = family;

    dir = XFRM_POLICY_OUT;
    if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT))
    {
	dir = XFRM_POLICY_IN;
    }

    if ((op & ERO_MASK) == ERO_DELETE)
    {
	req.u.id.dir = dir;
	req.n.nlmsg_type = XFRM_MSG_DELPOLICY;
	req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.id)));
    }
    else
    {
    	int src, dst;

	req.u.p.dir = dir;

    	src = req.u.p.sel.prefixlen_s;
    	dst = req.u.p.sel.prefixlen_d;
	if (dir != XFRM_POLICY_OUT) {
	    src = req.u.p.sel.prefixlen_d;
	    dst = req.u.p.sel.prefixlen_s;
	}
	req.u.p.priority = MIN_SPD_PRIORITY
	    + (((2 << shift) - src) << shift)
	    + (2 << shift) - dst;

	req.u.p.action = XFRM_POLICY_ALLOW;
	if (policy == IPSEC_POLICY_DISCARD)
	{
	    req.u.p.action = XFRM_POLICY_BLOCK;
	}
	req.u.p.lft.soft_use_expires_seconds = use_lifetime;
	req.u.p.lft.soft_byte_limit = XFRM_INF;
	req.u.p.lft.soft_packet_limit = XFRM_INF;
	req.u.p.lft.hard_byte_limit = XFRM_INF;
	req.u.p.lft.hard_packet_limit = XFRM_INF;

	req.n.nlmsg_type = XFRM_MSG_NEWPOLICY;
	if (op & (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT))
	{
	    req.n.nlmsg_type = XFRM_MSG_UPDPOLICY;
	}
	req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.p)));
    }

    if (policy == IPSEC_POLICY_IPSEC && (op & ERO_MASK) != ERO_DELETE)
    {
	struct rtattr *attr;
	struct xfrm_user_tmpl tmpl[4];
	int i;

	memset(tmpl, 0, sizeof(tmpl));
	for (i = 0; proto_info[i].proto; i++)
	{
	    tmpl[i].reqid = proto_info[i].reqid;
	    tmpl[i].id.proto = proto_info[i].proto;
	    tmpl[i].optional = proto_info[i].proto == IPPROTO_COMP;
	    tmpl[i].aalgos = tmpl[i].ealgos = tmpl[i].calgos = ~0;
	    tmpl[i].mode =
		proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL;

	    if (!tmpl[i].mode)
	    {
		continue;
	    }

	    ip2xfrm(this_host, &tmpl[i].saddr);
	    ip2xfrm(that_host, &tmpl[i].id.daddr);
	}

	attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
	attr->rta_type = XFRMA_TMPL;
	attr->rta_len = i * sizeof(tmpl[0]);
	memcpy(RTA_DATA(attr), tmpl, attr->rta_len);
	attr->rta_len = RTA_LENGTH(attr->rta_len);
	req.n.nlmsg_len += attr->rta_len;
    }

    enoent_ok = FALSE;
    if (op == ERO_DEL_INBOUND)
    {
	enoent_ok = TRUE;
    }
    else if (op == ERO_DELETE && ntohl(spi) == SPI_HOLD)
    {
	enoent_ok = TRUE;
    }

    ok = netlink_policy(&req.n, enoent_ok, text_said);
    switch (dir)
    {
    case XFRM_POLICY_IN:
	if (req.n.nlmsg_type == XFRM_MSG_DELPOLICY)
	{
	    req.u.id.dir = XFRM_POLICY_FWD;
	}
	else if (!ok)
	{
	    break;
	}
	else if (proto_info[0].encapsulation != ENCAPSULATION_MODE_TUNNEL
	&& satype != SADB_X_SATYPE_INT)
	{
	    break;
	}
	else
	{
	    req.u.p.dir = XFRM_POLICY_FWD;
	}
	ok &= netlink_policy(&req.n, enoent_ok, text_said);
	break;
    }

    return ok;
}