, 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; }
/** 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; }