Esempio n. 1
0
/** netlink_policy - 
 *
 * @param hdr - Data to check
 * @param enoent_ok - Boolean - OK or not OK.
 * @param text_said - String
 * @return boolean 
 */
static bool
netlink_policy(struct nlmsghdr *hdr, bool enoent_ok, const char *text_said)
{
    struct {
	struct nlmsghdr n;
	struct nlmsgerr e;
    } rsp;
    int error;

    rsp.n.nlmsg_type = NLMSG_ERROR;
    if (!send_netlink_msg(hdr, &rsp.n, sizeof(rsp), "policy", text_said))
    {
	return FALSE;
    }

    error = -rsp.e.error;
    if (!error)
    {
	return TRUE;
    }

    if (error == ENOENT && enoent_ok)
    {
	return TRUE;
    }

    loglog(RC_LOG_SERIOUS
	, "ERROR: netlink %s response for flow %s included errno %d: %s"
	, sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
	, text_said
	, error
	, strerror(error));
    return FALSE;
}
Esempio n. 2
0
/* function: send_ifaddrmsg
 * sends a netlink/ifaddrmsg message and hands the responses to the callbacks
 * type      - netlink message type
 * flags     - netlink message flags
 * ifa       - ifaddrmsg to send
 * callbacks - callbacks to use with the responses
 */
void send_ifaddrmsg(uint16_t type, uint16_t flags, struct ifaddrmsg *ifa, struct nl_cb *callbacks) {
  struct nl_msg *msg = NULL;

  msg = nlmsg_alloc_ifaddr(type, flags, ifa);
  if(!msg)
    return;

  send_netlink_msg(msg, callbacks);

  nlmsg_free(msg);
}
Esempio n. 3
0
/* function: netlink_sendrecv
 * send a nl_msg and return an int status - only supports OK/ERROR responses
 * msg - msg to send
 */
int netlink_sendrecv(struct nl_msg *msg) {
  struct nl_cb *callbacks = NULL;
  int retval = -EIO;

  callbacks = alloc_ack_callbacks(&retval);
  if(!callbacks) {
    return -ENOMEM;
  }

  send_netlink_msg(msg, callbacks);

  nl_cb_put(callbacks);

  return retval;
}
Esempio n. 4
0
/* function: get_default_route
 * finds the first default route with the given family and interface, returns the gateway (if it exists) in the struct
 * default_route - requested family and interface, and response storage
 */
int get_default_route(struct default_route_data *default_route) {
  struct rtmsg msg;
  struct nl_cb *callbacks = NULL;
  struct nl_msg *nlmsg = NULL;
  int retval = 0;

  default_route->reply_has_gateway = 0;
  default_route->reply_found_route = 0;

  memset(&msg,'\0',sizeof(msg));
  msg.rtm_family = default_route->request_family;
  msg.rtm_table = RT_TABLE_MAIN;
  msg.rtm_protocol = RTPROT_KERNEL;
  msg.rtm_scope = RT_SCOPE_UNIVERSE;

  callbacks = nl_cb_alloc(NL_CB_DEFAULT);
  if(!callbacks) {
    retval = -ENOMEM;
    goto cleanup;
  }
  // get_default_route_cb sets the response fields in default_route
  nl_cb_set(callbacks, NL_CB_VALID, NL_CB_CUSTOM, get_default_route_cb, default_route);
  nl_cb_err(callbacks, NL_CB_CUSTOM, error_handler, &retval);

  nlmsg = nlmsg_alloc_rtmsg(RTM_GETROUTE, NLM_F_REQUEST | NLM_F_ROOT, &msg);
  if(!nlmsg) {
    retval = -ENOMEM;
    goto cleanup;
  }
  send_netlink_msg(nlmsg, callbacks);

cleanup:
  if(callbacks)
    nl_cb_put(callbacks);
  if(nlmsg)
    nlmsg_free(nlmsg);

  return retval;
}
Esempio n. 5
0
/** netlink_del_sa - Delete an SA from the Kernel
 * 
 * @param sa Kernel SA to be deleted
 * @return bool True if successfull
 */
static bool
netlink_del_sa(const struct kernel_sa *sa)
{
    struct {
	struct nlmsghdr n;
	struct xfrm_usersa_id id;
	char data[1024];
    } req;

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

    ip2xfrm(sa->dst, &req.id.daddr);

    req.id.spi = sa->spi;
    req.id.family = sa->src->u.v4.sin_family;
    req.id.proto = sa->proto;

    req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));

    return send_netlink_msg(&req.n, NULL, 0, "Del SA", sa->text_said);
}
Esempio n. 6
0
static void
netlink_policy_expire(struct nlmsghdr *n)
{
    struct xfrm_user_polexpire *upe;
    struct {
	struct nlmsghdr n;
	struct xfrm_userpolicy_id id;
    } req;
    struct {
	struct nlmsghdr n;
	struct xfrm_userpolicy_info pol;
	char data[1024];
    } rsp;

    if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe)))
    {
	openswan_log("netlink_policy_expire got message with length %lu < %lu bytes; ignore message"
	    , (unsigned long) n->nlmsg_len
	    , (unsigned long) sizeof(*upe));
	return;
    }

    upe = NLMSG_DATA(n);
    req.id.dir = upe->pol.dir;
    req.id.index = upe->pol.index;
    req.n.nlmsg_flags = NLM_F_REQUEST;
    req.n.nlmsg_type = XFRM_MSG_GETPOLICY;
    req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)));

    rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY;
    if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?"))
    {
	return;
    }
    else if (rsp.n.nlmsg_type == NLMSG_ERROR)
    {
	DBG(DBG_KLIPS,
	    DBG_log("netlink_policy_expire: policy died on us: "
		    "dir=%d, index=%d"
		, req.id.dir, req.id.index));
	return;
    }
    else if (rsp.n.nlmsg_len < NLMSG_LENGTH(sizeof(rsp.pol)))
    {
	openswan_log("netlink_policy_expire: XFRM_MSG_GETPOLICY returned message with length %lu < %lu bytes; ignore message"
	    , (unsigned long) rsp.n.nlmsg_len
	    , (unsigned long) sizeof(rsp.pol));
	return;
    }
    else if (req.id.index != rsp.pol.index)
    {
	DBG(DBG_KLIPS,
	    DBG_log("netlink_policy_expire: policy was replaced: "
		    "dir=%d, oldindex=%d, newindex=%d"
		, req.id.dir, req.id.index, rsp.pol.index));
	return;
    }
    else if (upe->pol.curlft.add_time != rsp.pol.curlft.add_time)
    {
	DBG(DBG_KLIPS,
	    DBG_log("netlink_policy_expire: policy was replaced "
		    " and you have won the lottery: "
		    "dir=%d, index=%d"
		, req.id.dir, req.id.index));
	return;
    }

    switch (upe->pol.dir)
    {
    case XFRM_POLICY_OUT:
	netlink_shunt_expire(&rsp.pol);
	break;
    }
}
Esempio n. 7
0
/** netlink_add_sa - Add an SA into the kernel SPDB via netlink
 *
 * @param sa Kernel SA to add/modify
 * @param replace boolean - true if this replaces an existing SA
 * @return bool True if successfull
 */
static bool
netlink_add_sa(const struct kernel_sa *sa, bool replace)
{
    struct {
	struct nlmsghdr n;
	struct xfrm_usersa_info p;
	char data[1024];
    } req;
    struct rtattr *attr;

    memset(&req, 0, sizeof(req));
    req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.n.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;

    ip2xfrm(sa->src, &req.p.saddr);
    ip2xfrm(sa->dst, &req.p.id.daddr);

    req.p.id.spi = sa->spi;
    req.p.id.proto = satype2proto(sa->satype);
    req.p.family = sa->src->u.v4.sin_family;
    req.p.mode = (sa->encapsulation == ENCAPSULATION_MODE_TUNNEL);
    req.p.replay_window = sa->replay_window;
    req.p.reqid = sa->reqid;
    req.p.lft.soft_byte_limit = XFRM_INF;
    req.p.lft.soft_packet_limit = XFRM_INF;
    req.p.lft.hard_byte_limit = XFRM_INF;
    req.p.lft.hard_packet_limit = XFRM_INF;

    req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.p)));

    attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);

    if (sa->authkeylen)
    {
	struct xfrm_algo algo;
	const char *name;

	name = sparse_name(aalg_list, sa->authalg);
	if (!name) {
	    loglog(RC_LOG_SERIOUS, "unknown authentication algorithm: %u"
		, sa->authalg);
	    return FALSE;
	}

	strcpy(algo.alg_name, name);
	algo.alg_key_len = sa->authkeylen * BITS_PER_BYTE;

	attr->rta_type = XFRMA_ALG_AUTH;
	attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->authkeylen);

	memcpy(RTA_DATA(attr), &algo, sizeof(algo));
	memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->authkey
	    , sa->authkeylen);

	req.n.nlmsg_len += attr->rta_len;
	attr = (struct rtattr *)((char *)attr + attr->rta_len);
    }

    if (sa->enckeylen)
    {
	struct xfrm_algo algo;
	const char *name;

	name = sparse_name(ealg_list, sa->encalg);
	if (!name) {
	    loglog(RC_LOG_SERIOUS, "unknown encryption algorithm: %u"
		, sa->encalg);
	    return FALSE;
	}

	strcpy(algo.alg_name, name);
	algo.alg_key_len = sa->enckeylen * BITS_PER_BYTE;

	attr->rta_type = XFRMA_ALG_CRYPT;
	attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->enckeylen);

	memcpy(RTA_DATA(attr), &algo, sizeof(algo));
	memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->enckey
	    , sa->enckeylen);

	req.n.nlmsg_len += attr->rta_len;
	attr = (struct rtattr *)((char *)attr + attr->rta_len);
    }

    if (sa->satype == SADB_X_SATYPE_COMP)
    {
	struct xfrm_algo algo;
	const char *name;

	name = sparse_name(calg_list, sa->encalg);
	if (!name) {
	    loglog(RC_LOG_SERIOUS, "unknown compression algorithm: %u"
		, sa->encalg);
	    return FALSE;
	}

	strcpy(algo.alg_name, name);
	algo.alg_key_len = 0;

	attr->rta_type = XFRMA_ALG_COMP;
	attr->rta_len = RTA_LENGTH(sizeof(algo));

	memcpy(RTA_DATA(attr), &algo, sizeof(algo));

	req.n.nlmsg_len += attr->rta_len;
	attr = (struct rtattr *)((char *)attr + attr->rta_len);
    }

#ifdef NAT_TRAVERSAL
    if (sa->natt_type)
    {
	struct xfrm_encap_tmpl natt;

	natt.encap_type = sa->natt_type;
	natt.encap_sport = ntohs(sa->natt_sport);
	natt.encap_dport = ntohs(sa->natt_dport);
	memset (&natt.encap_oa, 0, sizeof (natt.encap_oa));

	attr->rta_type = XFRMA_ENCAP;
	attr->rta_len = RTA_LENGTH(sizeof(natt));

	memcpy(RTA_DATA(attr), &natt, sizeof(natt));

	req.n.nlmsg_len += attr->rta_len;
	attr = (struct rtattr *)((char *)attr + attr->rta_len);
    }
#endif

    return send_netlink_msg(&req.n, NULL, 0, "Add SA", sa->text_said);
}
Esempio n. 8
0
static ipsec_spi_t
netlink_get_spi(const ip_address *src
, const ip_address *dst
, int proto
, bool tunnel_mode
, unsigned reqid
, ipsec_spi_t min
, ipsec_spi_t max
, const char *text_said)
{
    struct {
	struct nlmsghdr n;
	struct xfrm_userspi_info spi;
    } req;
    struct {
	struct nlmsghdr n;
	union {
	    struct nlmsgerr e;
	    struct xfrm_usersa_info sa;
	} u;
	char data[1024];
    } rsp;

    memset(&req, 0, sizeof(req));
    req.n.nlmsg_flags = NLM_F_REQUEST;
    req.n.nlmsg_type = XFRM_MSG_ALLOCSPI;

    ip2xfrm(src, &req.spi.info.saddr);
    ip2xfrm(dst, &req.spi.info.id.daddr);
    req.spi.info.mode = tunnel_mode;
    req.spi.info.reqid = reqid;
    req.spi.info.id.proto = proto;
    req.spi.info.family = src->u.v4.sin_family;
    req.spi.min = min;
    req.spi.max = max;

    req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.spi)));

    rsp.n.nlmsg_type = XFRM_MSG_NEWSA;
    if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SPI", text_said))
	return 0;
    else if (rsp.n.nlmsg_type == NLMSG_ERROR)
    {
	loglog(RC_LOG_SERIOUS
	    , "ERROR: netlink_get_spi for %s failed with errno %d: %s"
	    , text_said
	    , -rsp.u.e.error
	    , strerror(-rsp.u.e.error));
	return 0;
    }
    else if (rsp.n.nlmsg_len < NLMSG_LENGTH(sizeof(rsp.u.sa)))
    {
	openswan_log("netlink_get_spi: XFRM_MSG_ALLOCSPI returned message with length %lu < %lu bytes; ignore message"
	    , (unsigned long) rsp.n.nlmsg_len
	    , (unsigned long) sizeof(rsp.u.sa));
	return 0;
    }

    DBG(DBG_KLIPS,
	DBG_log("netlink_get_spi: allocated 0x%x for %s"
	    , ntohl(rsp.u.sa.id.spi), text_said));
    return rsp.u.sa.id.spi;
}