⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernel_netlink.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
	{	    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;}/** 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 boolnetlink_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);}/** netlink_del_sa - Delete an SA from the Kernel *  * @param sa Kernel SA to be deleted * @return bool True if successfull */static boolnetlink_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);}static voidlinux_pfkey_register_response(const struct sadb_msg *msg){    switch (msg->sadb_msg_satype)    {    case SADB_SATYPE_ESP:#ifdef KERNEL_ALG	    kernel_alg_register_pfkey(msg, msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);#endif	    break;    case SADB_X_SATYPE_IPCOMP:	can_do_IPcomp = TRUE;	break;    default:	break;    }}/** linux_pfkey_register - Register via PFKEY our capabilities * */static voidlinux_pfkey_register(void){    pfkey_register_proto(SADB_SATYPE_AH, "AH");    pfkey_register_proto(SADB_SATYPE_ESP, "ESP");    pfkey_register_proto(SADB_X_SATYPE_IPCOMP, "IPCOMP");    pfkey_close();}/** Create ip_address out of xfrm_address_t. *  * @param family  * @param src xfrm formatted IP address * @param dst ip_address formatted destination  * @return err_t NULL if okay, otherwise an error */static err_txfrm_to_ip_address(unsigned family, const xfrm_address_t *src, ip_address *dst){    switch (family)    {    case AF_INET: /* IPv4 */	initaddr((const void *) &src->a4, sizeof(src->a4), family, dst);	return NULL;    case AF_INET6: /* IPv6 */	initaddr((const void *) &src->a6, sizeof(src->a6), family, dst);	return NULL;    default:	return "unknown address family";    }}static voidnetlink_acquire(struct nlmsghdr *n){    struct xfrm_user_acquire *acquire;    const xfrm_address_t *srcx, *dstx;    int src_proto, dst_proto;    ip_address src, dst;    ip_subnet ours, his;    unsigned family;    unsigned transport_proto;    err_t ugh = NULL;    if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*acquire)))    {	openswan_log("netlink_acquire got message with length %lu < %lu bytes; ignore message"	    , (unsigned long) n->nlmsg_len	    , (unsigned long) sizeof(*acquire));	return;    }    acquire = NLMSG_DATA(n);    srcx = &acquire->sel.saddr;    dstx = &acquire->sel.daddr;    family = acquire->policy.sel.family;    transport_proto = acquire->sel.proto;    src_proto = 0;   /* XXX-MCR where to get protocol from? */    dst_proto = 0;   /* ditto */    /* XXX also the type of src/dst should be checked to make sure     *     that they aren't v4 to v6 or something goofy     */    if (!(ugh = xfrm_to_ip_address(family, srcx, &src))	&& !(ugh = xfrm_to_ip_address(family, dstx, &dst))	&& !(ugh = src_proto == dst_proto? NULL : "src and dst protocols differ")	&& !(ugh = addrtosubnet(&src, &ours))	&& !(ugh = addrtosubnet(&dst, &his)))      record_and_initiate_opportunistic(&ours, &his, transport_proto					  , "%acquire-netlink");    if (ugh != NULL)	openswan_log("XFRM_MSG_ACQUIRE message from kernel malformed: %s", ugh);}static voidnetlink_shunt_expire(struct xfrm_userpolicy_info *pol){    const xfrm_address_t *srcx, *dstx;    ip_address src, dst;    unsigned family;    unsigned transport_proto;    err_t ugh = NULL;      srcx = &pol->sel.saddr;    dstx = &pol->sel.daddr;    family = pol->sel.family;    transport_proto = pol->sel.proto;    if ((ugh = xfrm_to_ip_address(family, srcx, &src))    || (ugh = xfrm_to_ip_address(family, dstx, &dst)))    {	openswan_log("XFRM_MSG_POLEXPIRE message from kernel malformed: %s", ugh);	return;    }    replace_bare_shunt(&src, &dst		       , BOTTOM_PRIO		       , SPI_PASS		       , FALSE		       , transport_proto		       , "delete expired bare shunt");}static voidnetlink_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;    }}static boolnetlink_get(void){    struct {	struct nlmsghdr n;	char data[1024];    } rsp;    ssize_t r;    struct sockaddr_nl addr;    socklen_t alen;    alen = sizeof(addr);    r = recvfrom(netlink_bcast_fd, &rsp, sizeof(rsp), 0	, (struct sockaddr *)&addr, &alen);    if (r < 0)    {	if (errno == EAGAIN)	    return FALSE;	if (errno != EINTR)	    log_errno((e, "recvfrom() failed in netlink_get"));	return TRUE;    }    else if ((size_t) r < sizeof(rsp.n))    {	openswan_log("netlink_get read truncated message: %ld bytes; ignore message"	    , (long) r);	return TRUE;    }    else if (addr.nl_pid != 0)    {	/* not for us: ignore */	DBG(DBG_KLIPS,	    DBG_log("netlink_get: ignoring %s message from process %u"		, sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)		, addr.nl_pid));	return TRUE;    }    else if ((size_t) r != rsp.n.nlmsg_len)    {	openswan_log("netlink_get read message with length %ld that doesn't equal nlmsg_len %lu bytes; ignore message"	    , (long) r	    , (unsigned long) rsp.n.nlmsg_len);	return TRUE;    }    DBG(DBG_KLIPS,	DBG_log("netlink_get: %s message"		, sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)));    switch (rsp.n.nlmsg_type)    {    case XFRM_MSG_ACQUIRE:	netlink_acquire(&rsp.n);	break;    case XFRM_MSG_POLEXPIRE:	netlink_policy_expire(&rsp.n);	break;    default:	/* ignored */	break;    }    return TRUE;}static voidnetlink_process_msg(void){    while (netlink_get())	;}static ipsec_spi_tnetlink_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;}const struct kernel_ops linux_kernel_ops = {	type: KERNEL_TYPE_LINUX,	inbound_eroute: 1,	policy_lifetime: 1,	async_fdp: &netlink_bcast_fd,	init: init_netlink,	pfkey_register: linux_pfkey_register,	pfkey_register_response: linux_pfkey_register_response,	process_msg: netlink_process_msg,	raw_eroute: netlink_raw_eroute,	add_sa: netlink_add_sa,	del_sa: netlink_del_sa,	process_queue: NULL,	grp_sa: NULL,	get_spi: netlink_get_spi,};#endif /* linux && KLIPS */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -