diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 6b4c0bb7f..65151353f 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,12 @@ MODULE_ALIAS("ip6t_RTPENGINE"); #define xt_action_param xt_target_param #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) +#define PAR_STATE_NET(p) (p)->state->net +#else +#define PAR_STATE_NET(p) (p)->net +#endif + #if 0 #define _s_lock(l, f) do { \ printk(KERN_DEBUG "[PID %i %s:%i] acquiring lock %s\n", \ @@ -3785,12 +3792,15 @@ static ssize_t proc_control_read(struct file *file, char __user *ubuf, size_t bu +// par can be NULL static int send_proxy_packet4(struct sk_buff *skb, struct re_address *src, struct re_address *dst, unsigned char tos, const struct xt_action_param *par) { struct iphdr *ih; struct udphdr *uh; unsigned int datalen; + struct net *net; + struct rtable *rt; datalen = skb->len; @@ -3823,37 +3833,34 @@ static int send_proxy_packet4(struct sk_buff *skb, struct re_address *src, struc uh->check = csum_tcpudp_magic(src->u.ipv4, dst->u.ipv4, datalen, IPPROTO_UDP, csum_partial(uh, datalen, 0)); if (uh->check == 0) uh->check = CSUM_MANGLED_0; - skb->protocol = htons(ETH_P_IP); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,9) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(5,4,78) && LINUX_VERSION_CODE < KERNEL_VERSION(5,5,0)) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,158) && LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)) - if (ip_route_me_harder(par->state->net, par->state->sk, skb, RTN_UNSPEC)) -#elif defined(RHEL_RELEASE_CODE) && LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0) && \ - RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(8,4) - if (ip_route_me_harder(par->state->net, par->state->sk, skb, RTN_UNSPEC)) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (ip_route_me_harder(par->state->net, skb, RTN_UNSPEC)) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) - if (ip_route_me_harder(par->net, skb, RTN_UNSPEC)) -#else - if (ip_route_me_harder(skb, RTN_UNSPEC)) -#endif + + net = NULL; + if (par) + net = PAR_STATE_NET(par); + if (!net && current && current->nsproxy) + net = current->nsproxy->net_ns; + if (!net) + goto drop; + + rt = ip_route_output(net, dst->u.ipv4, src->u.ipv4, tos, 0); + if (IS_ERR(rt)) + goto drop; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->dst); + + if (skb_dst(skb)->error) goto drop; skb->ip_summed = CHECKSUM_NONE; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - ip_select_ident(par->state->net, skb, NULL); - ip_send_check(ih); - ip_local_out(par->state->net, skb->sk, skb); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) - ip_select_ident(par->net, skb, NULL); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) + ip_select_ident(net, skb, NULL); ip_send_check(ih); - ip_local_out(par->net, skb->sk, skb); + ip_local_out(net, skb->sk, skb); #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) - ip_select_ident(par->net, skb, NULL); + ip_select_ident(net, skb, NULL); #elif (LINUX_VERSION_CODE == KERNEL_VERSION(3,10,0) && RHEL_MAJOR == 7) /* CentOS 7 */ /* nothing */ #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,10) \ @@ -3888,12 +3895,16 @@ drop: +// par can be NULL static int send_proxy_packet6(struct sk_buff *skb, struct re_address *src, struct re_address *dst, unsigned char tos, const struct xt_action_param *par) { struct ipv6hdr *ih; struct udphdr *uh; unsigned int datalen; + struct net *net; + struct dst_entry *dst_entry; + struct flowi6 fl6; datalen = skb->len; @@ -3926,30 +3937,35 @@ static int send_proxy_packet6(struct sk_buff *skb, struct re_address *src, struc uh->check = csum_ipv6_magic(&ih->saddr, &ih->daddr, datalen, IPPROTO_UDP, csum_partial(uh, datalen, 0)); if (uh->check == 0) uh->check = CSUM_MANGLED_0; - skb->protocol = htons(ETH_P_IPV6); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,9) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(5,4,78) && LINUX_VERSION_CODE < KERNEL_VERSION(5,5,0)) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,158) && LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)) - if (ip6_route_me_harder(par->state->net, par->state->sk, skb)) -#elif defined(RHEL_RELEASE_CODE) && LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0) && \ - RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(8,4) - if (ip6_route_me_harder(par->state->net, par->state->sk, skb)) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (ip6_route_me_harder(par->state->net, skb)) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) - if (ip6_route_me_harder(par->net, skb)) -#else - if (ip6_route_me_harder(skb)) -#endif + + net = NULL; + if (par) + net = PAR_STATE_NET(par); + if (!net && current && current->nsproxy) + net = current->nsproxy->net_ns; + if (!net) + goto drop; + + memset(&fl6, 0, sizeof(fl6)); + memcpy(&fl6.saddr, src->u.ipv6, sizeof(fl6.saddr)); + memcpy(&fl6.daddr, dst->u.ipv6, sizeof(fl6.daddr)); + fl6.flowi6_mark = skb->mark; + + dst_entry = ip6_route_output(net, NULL, &fl6); + if (!dst_entry) + goto drop; + if (dst_entry->error) { + dst_release(dst_entry); goto drop; + } + skb_dst_drop(skb); + skb_dst_set(skb, dst_entry); skb->ip_summed = CHECKSUM_NONE; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - ip6_local_out(par->state->net, skb->sk, skb); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) - ip6_local_out(par->net, skb->sk, skb); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) + ip6_local_out(net, skb->sk, skb); #else ip6_local_out(skb); #endif @@ -4581,6 +4597,56 @@ static struct sk_buff *intercept_skb_copy(struct sk_buff *oskb, const struct re_ return ret; } +static void proxy_packet_output_rtp(struct sk_buff *skb, struct rtpengine_output *o, + int rtp_pt_idx, + struct rtp_parsed *rtp, int ssrc_idx) +{ + unsigned int pllen; + uint64_t pkt_idx; + int i; + + if (!rtp->ok) + return; + + // pattern rewriting + if (rtp_pt_idx >= 0 && o->output.pt_output[rtp_pt_idx].replace_pattern_len) { + if (o->output.pt_output[rtp_pt_idx].replace_pattern_len == 1) + memset(rtp->payload, o->output.pt_output[rtp_pt_idx].replace_pattern[0], + rtp->payload_len); + else { + for (i = 0; i < rtp->payload_len; + i += o->output.pt_output[rtp_pt_idx].replace_pattern_len) + memcpy(&rtp->payload[i], + o->output.pt_output[rtp_pt_idx].replace_pattern, + o->output.pt_output[rtp_pt_idx].replace_pattern_len); + } + } + + // SSRC substitution and seq manipulation + if (likely(ssrc_idx >= 0)) { + rtp->header->seq_num = htons(ntohs(rtp->header->seq_num) + + o->output.seq_offset[ssrc_idx]); + if (o->output.ssrc_subst && likely(o->output.ssrc_out[ssrc_idx])) + rtp->header->ssrc = o->output.ssrc_out[ssrc_idx]; + } + + // SRTP + pkt_idx = packet_index(&o->encrypt, &o->output.encrypt, rtp->header, ssrc_idx); + pllen = rtp->payload_len; + srtp_encrypt(&o->encrypt, &o->output.encrypt, rtp, pkt_idx); + srtp_authenticate(&o->encrypt, &o->output.encrypt, rtp, pkt_idx); + skb_put(skb, rtp->payload_len - pllen); +} + +static int send_proxy_packet_output(struct sk_buff *skb, struct rtpengine_target *g, + int rtp_pt_idx, + struct rtpengine_output *o, struct rtp_parsed *rtp, int ssrc_idx, + const struct xt_action_param *par) +{ + proxy_packet_output_rtp(skb, o, rtp_pt_idx, rtp, ssrc_idx); + return send_proxy_packet(skb, &o->output.src_addr, &o->output.dst_addr, o->output.tos, par); +} + @@ -4684,7 +4750,7 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, int error_nf_action = XT_CONTINUE; int rtp_pt_idx = -2; int ssrc_idx = -1; - unsigned int datalen, pllen, datalen_out; + unsigned int datalen, datalen_out; struct rtp_parsed rtp, rtp2; ssize_t offset; uint64_t pkt_idx; @@ -4845,40 +4911,7 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, rtp2.header = (void *) (((char *) rtp2.header) + offset); rtp2.payload = (void *) (((char *) rtp2.payload) + offset); - // pattern rewriting - if (rtp_pt_idx >= 0 && o->output.pt_output[rtp_pt_idx].replace_pattern_len && rtp2.ok) { - if (o->output.pt_output[rtp_pt_idx].replace_pattern_len == 1) - memset(rtp2.payload, o->output.pt_output[rtp_pt_idx].replace_pattern[0], - rtp2.payload_len); - else { - for (i = 0; i < rtp2.payload_len; - i += o->output.pt_output[rtp_pt_idx].replace_pattern_len) - memcpy(&rtp2.payload[i], - o->output.pt_output[rtp_pt_idx].replace_pattern, - o->output.pt_output[rtp_pt_idx].replace_pattern_len); - } - } - - if (rtp2.ok) { - // SSRC substitution and seq manipulation - if (ssrc_idx != -1) { - rtp2.header->seq_num = htons(ntohs(rtp2.header->seq_num) - + o->output.seq_offset[ssrc_idx]); - if (o->output.ssrc_subst && o->output.ssrc_out[ssrc_idx]) - rtp2.header->ssrc = o->output.ssrc_out[ssrc_idx]; - } - - pkt_idx = packet_index(&o->encrypt, &o->output.encrypt, rtp2.header, ssrc_idx); - pllen = rtp2.payload_len; - srtp_encrypt(&o->encrypt, &o->output.encrypt, &rtp2, pkt_idx); - srtp_authenticate(&o->encrypt, &o->output.encrypt, &rtp2, pkt_idx); - skb_put(skb2, rtp2.payload_len - pllen); - } - - datalen_out = skb2->len; - - err = send_proxy_packet(skb2, &o->output.src_addr, &o->output.dst_addr, o->output.tos, par); - + err = send_proxy_packet_output(skb2, g, rtp_pt_idx, o, &rtp2, ssrc_idx, par); if (err) { atomic64_inc(&g->stats_in.errors); atomic64_inc(&o->stats_out.errors);