diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 045706697..a75f5720c 100755 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,7 +9,7 @@ jobs: build: strategy: matrix: - OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, x86_64] + OMR_TARGET: [bpi-r1, bpi-r2, bpi-r64, rpi2, rpi4, wrt32x, espressobin, r2s, rpi3, wrt3200acm, x86, x86_64, ubnt-erx, r4s] runs-on: ubuntu-latest continue-on-error: true diff --git a/README.md b/README.md index 6483e1fcf..e92835abd 100755 --- a/README.md +++ b/README.md @@ -163,6 +163,21 @@ This is used to bypass a protocol *Description:* A middlebox detection tool +## Shortcut-FE +*Source:* [https://github.com/coolsnowwolf/lede/tree/master/package/lean/shortcut-fe](https://github.com/coolsnowwolf/lede/tree/master/package/lean/shortcut-fe) + +*Description:* Shortcut is an in-Linux-kernel IP packet forwarding engine. + + +## V2Ray +*Source:* [https://github.com/v2fly/v2ray-core](https://github.com/v2fly/v2ray-core) + +*Description:* A platform for building proxies to bypass network restrictions. + +This is used as proxy, alternative to Shadowsocks + + + # License [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FYsurac%2Fopenmptcprouter-feeds.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FYsurac%2Fopenmptcprouter-feeds?ref=badge_large) diff --git a/aquantia/Makefile b/aquantia/Makefile new file mode 100644 index 000000000..dc8c8f46a --- /dev/null +++ b/aquantia/Makefile @@ -0,0 +1,41 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=kmod-aquantia +PKG_VERSION:=1.0 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/phy-aquantia + SUBMENU:=Network Devices + TITLE:=aQuantia device support + DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-hwmon-core +kmod-libphy + KCONFIG:=CONFIG_AQUANTIA_PHY + HIDDEN:=1 + FILES:=$(LINUX_DIR)/drivers/net/phy/aquantia.ko + AUTOLOAD:=$(call AutoProbe,aquantia) +endef + +define KernelPackage/phy-aquantia/description + Kernel modules for aQuantia Ethernet adapters. +endef + +define KernelPackage/atlantic + SUBMENU:=Network Devices + TITLE:=aQuantia AQtion(tm) Support + DEPENDS:=@PCI_SUPPORT @TARGET_x86_64 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-phy-aquantia + KCONFIG:=CONFIG_AQTION + FILES:=$(LINUX_DIR)/drivers/net/ethernet/aquantia/atlantic/atlantic.ko + AUTOLOAD:=$(call AutoProbe,atlantic) +endef + +define KernelPackage/atlantic/description + Kernel modules for the aQuantia AQtion(tm) Ethernet card +endef + +define Build/Compile +endef + +$(eval $(call KernelPackage,phy-aquantia)) +$(eval $(call KernelPackage,atlantic)) \ No newline at end of file diff --git a/fast-classifier/Makefile b/fast-classifier/Makefile new file mode 100644 index 000000000..29d024e7b --- /dev/null +++ b/fast-classifier/Makefile @@ -0,0 +1,92 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=fast-classifier +PKG_RELEASE:=1 +PKG_CONFIG_DEPENDS := CONFIG_IPV6 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/$(PKG_NAME)/Default + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe + TITLE:=Kernel driver for FAST Classifier + FILES:=$(PKG_BUILD_DIR)/fast-classifier.ko + KCONFIG:=CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y CONFIG_NF_CONNTRACK_MARK=y + PROVIDES:=$(PKG_NAME) +endef + +define KernelPackage/$(PKG_NAME) + $(call KernelPackage/$(PKG_NAME)/Default) +endef + +define KernelPackage/$(PKG_NAME)-noload + $(call KernelPackage/$(PKG_NAME)/Default) +endef + +define KernelPackage/$(PKG_NAME)/Default/description +FAST Classifier talks to SFE to make decisions about offloading connections +endef + +define KernelPackage/$(PKG_NAME)/description +$(call KernelPackage/$(PKG_NAME)/Default/description) +endef + +define KernelPackage/$(PKG_NAME)-noload/description +$(call KernelPackage/$(PKG_NAME)/Default/description) + +This package does not load $(PKG_NAME) at boot by default +endef + +define Package/fast-classifier-example + TITLE:=Example user space program for fast-classifier + DEPENDS:=+libnl +kmod-fast-classifier +endef + +define Package/fast-classifier-example/description +Example user space program that communicates with fast +classifier kernel module +endef + +SFE_MAKE_OPTS:=SFE_SUPPORT_IPV6=$(if $(CONFIG_IPV6),y,n) + +define Build/Compile/kmod + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(SFE_MAKE_OPTS) \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + CONFIG_FAST_CLASSIFIER=m \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + modules +endef + +define Build/Compile/example + $(TARGET_CC) -o $(PKG_BUILD_DIR)/userspace_fast_classifier \ + -I $(PKG_BUILD_DIR) \ + -I$(STAGING_DIR)/usr/include/libnl \ + -I$(STAGING_DIR)/usr/include/libnl3 \ + -lnl-genl-3 -lnl-3 \ + $(PKG_BUILD_DIR)/nl_classifier_test.c +endef + +define Build/Compile + $(Build/Compile/kmod) + $(if $(CONFIG_PACKAGE_fast-classifier-example),$(Build/Compile/example)) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/fast-classifier.h $(1)/usr/include/ +endef + + +define Package/fast-classifier-example/install + $(INSTALL_DIR) $(1)/sbin + $(CP) $(PKG_BUILD_DIR)/userspace_fast_classifier $(1)/sbin/ +endef + +$(eval $(call KernelPackage,$(PKG_NAME))) +$(eval $(call KernelPackage,$(PKG_NAME)-noload)) +#$(eval $(call BuildPackage,fast-classifier-example)) diff --git a/fast-classifier/src/Makefile b/fast-classifier/src/Makefile new file mode 100644 index 000000000..58dd06e01 --- /dev/null +++ b/fast-classifier/src/Makefile @@ -0,0 +1,10 @@ +obj-$(CONFIG_FAST_CLASSIFIER) += fast-classifier.o + +ifeq ($(SFE_SUPPORT_IPV6),) +SFE_SUPPORT_IPV6=y +endif +ccflags-$(SFE_SUPPORT_IPV6) += -DSFE_SUPPORT_IPV6 + +ccflags-y += -I$(obj)/../shortcut-fe + +obj ?= . diff --git a/fast-classifier/src/fast-classifier.c b/fast-classifier/src/fast-classifier.c new file mode 100644 index 000000000..7ca5d973b --- /dev/null +++ b/fast-classifier/src/fast-classifier.c @@ -0,0 +1,1976 @@ +/* + * fast-classifier.c + * Shortcut forwarding engine connection manager. + * fast-classifier + * + * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sfe_backport.h" +#include "sfe.h" +#include "sfe_cm.h" +#include "fast-classifier.h" + +typedef enum fast_classifier_exception { + FAST_CL_EXCEPTION_PACKET_BROADCAST, + FAST_CL_EXCEPTION_PACKET_MULTICAST, + FAST_CL_EXCEPTION_NO_IIF, + FAST_CL_EXCEPTION_NO_CT, + FAST_CL_EXCEPTION_CT_NO_TRACK, + FAST_CL_EXCEPTION_CT_NO_CONFIRM, + FAST_CL_EXCEPTION_CT_IS_ALG, + FAST_CL_EXCEPTION_IS_IPV4_MCAST, + FAST_CL_EXCEPTION_IS_IPV6_MCAST, + FAST_CL_EXCEPTION_TCP_NOT_ASSURED, + FAST_CL_EXCEPTION_TCP_NOT_ESTABLISHED, + FAST_CL_EXCEPTION_UNKNOW_PROTOCOL, + FAST_CL_EXCEPTION_NO_SRC_DEV, + FAST_CL_EXCEPTION_NO_SRC_XLATE_DEV, + FAST_CL_EXCEPTION_NO_DEST_DEV, + FAST_CL_EXCEPTION_NO_DEST_XLATE_DEV, + FAST_CL_EXCEPTION_NO_BRIDGE, + FAST_CL_EXCEPTION_LOCAL_OUT, + FAST_CL_EXCEPTION_WAIT_FOR_ACCELERATION, + FAST_CL_EXCEPTION_UPDATE_PROTOCOL_FAIL, + FAST_CL_EXCEPTION_CT_DESTROY_MISS, + FAST_CL_EXCEPTION_MAX +} fast_classifier_exception_t; + +static char *fast_classifier_exception_events_string[FAST_CL_EXCEPTION_MAX] = { + "PACKET_BROADCAST", + "PACKET_MULTICAST", + "NO_IIF", + "NO_CT", + "CT_NO_TRACK", + "CT_NO_CONFIRM", + "CT_IS_ALG", + "IS_IPV4_MCAST", + "IS_IPV6_MCAST", + "TCP_NOT_ASSURED", + "TCP_NOT_ESTABLISHED", + "UNKNOW_PROTOCOL", + "NO_SRC_DEV", + "NO_SRC_XLATE_DEV", + "NO_DEST_DEV", + "NO_DEST_XLATE_DEV", + "NO_BRIDGE", + "LOCAL_OUT", + "WAIT_FOR_ACCELERATION", + "UPDATE_PROTOCOL_FAIL", + "CT_DESTROY_MISS", +}; + +/* + * Per-module structure. + */ +struct fast_classifier { + spinlock_t lock; /* Lock for SMP correctness */ + + /* + * Control state. + */ + struct kobject *sys_fast_classifier; /* sysfs linkage */ + + /* + * Callback notifiers. + */ + struct notifier_block dev_notifier; /* Device notifier */ + struct notifier_block inet_notifier; /* IPv4 notifier */ + struct notifier_block inet6_notifier; /* IPv6 notifier */ + u32 exceptions[FAST_CL_EXCEPTION_MAX]; +}; + +static struct fast_classifier __sc; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) +static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = { + [FAST_CLASSIFIER_A_TUPLE] = { + .type = NLA_UNSPEC, + .len = sizeof(struct fast_classifier_tuple) + }, +}; +#endif /*KERNEL_VERSION(5, 2, 0)*/ + +static struct genl_multicast_group fast_classifier_genl_mcgrp[] = { + { + .name = FAST_CLASSIFIER_GENL_MCGRP, + }, +}; + +static int fast_classifier_offload_genl_msg(struct sk_buff *skb, struct genl_info *info); +static int fast_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, struct netlink_callback *cb); + +static struct genl_ops fast_classifier_gnl_ops[] = { + { + .cmd = FAST_CLASSIFIER_C_OFFLOAD, + .flags = 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) + .policy = fast_classifier_genl_policy, +#endif /*KERNEL_VERSION(5, 2, 0)*/ + .doit = fast_classifier_offload_genl_msg, + .dumpit = NULL, + }, + { + .cmd = FAST_CLASSIFIER_C_OFFLOADED, + .flags = 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) + .policy = fast_classifier_genl_policy, +#endif /*KERNEL_VERSION(5, 2, 0)*/ + .doit = NULL, + .dumpit = fast_classifier_nl_genl_msg_DUMP, + }, + { + .cmd = FAST_CLASSIFIER_C_DONE, + .flags = 0, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) + .policy = fast_classifier_genl_policy, +#endif /*KERNEL_VERSION(5, 2, 0)*/ + .doit = NULL, + .dumpit = fast_classifier_nl_genl_msg_DUMP, + }, +}; + +static struct genl_family fast_classifier_gnl_family = { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)) + .id = GENL_ID_GENERATE, +#endif /*KERNEL_VERSION(4, 10, 0)*/ + .hdrsize = FAST_CLASSIFIER_GENL_HDRSIZE, + .name = FAST_CLASSIFIER_GENL_NAME, + .version = FAST_CLASSIFIER_GENL_VERSION, + .maxattr = FAST_CLASSIFIER_A_MAX, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) + .ops = fast_classifier_gnl_ops, + .n_ops = ARRAY_SIZE(fast_classifier_gnl_ops), + .mcgrps = fast_classifier_genl_mcgrp, + .n_mcgrps = ARRAY_SIZE(fast_classifier_genl_mcgrp), +#endif /*KERNEL_VERSION(4, 10, 0)*/ +}; + +static atomic_t offload_msgs = ATOMIC_INIT(0); +static atomic_t offload_no_match_msgs = ATOMIC_INIT(0); +static atomic_t offloaded_msgs = ATOMIC_INIT(0); +static atomic_t done_msgs = ATOMIC_INIT(0); + +static atomic_t offloaded_fail_msgs = ATOMIC_INIT(0); +static atomic_t done_fail_msgs = ATOMIC_INIT(0); + +/* + * Accelerate incoming packets destined for bridge device + * If a incoming packet is ultimatly destined for + * a bridge device we will first see the packet coming + * from the phyiscal device, we can skip straight to + * processing the packet like it came from the bridge + * for some more performance gains + * + * This only works when the hook is above the bridge. We + * only implement ingress for now, because for egress we + * want to have the bridge devices qdiscs be used. + */ +static bool skip_to_bridge_ingress; + +/* + * fast_classifier_incr_exceptions() + * increase an exception counter. + */ +static inline void fast_classifier_incr_exceptions(fast_classifier_exception_t except) +{ + struct fast_classifier *sc = &__sc; + + spin_lock_bh(&sc->lock); + sc->exceptions[except]++; + spin_unlock_bh(&sc->lock); +} + +/* + * fast_classifier_recv() + * Handle packet receives. + * + * Returns 1 if the packet is forwarded or 0 if it isn't. + */ +int fast_classifier_recv(struct sk_buff *skb) +{ + struct net_device *dev; + struct net_device *master_dev = NULL; + int ret = 0; + + /* + * We know that for the vast majority of packets we need the transport + * layer header so we may as well start to fetch it now! + */ + prefetch(skb->data + 32); + barrier(); + + dev = skb->dev; + + /* + * Process packet like it arrived on the bridge device + */ + if (skip_to_bridge_ingress && + (dev->priv_flags & IFF_BRIDGE_PORT)) { + master_dev = sfe_dev_get_master(dev); + if (!master_dev) { + DEBUG_WARN("master dev is NULL %s\n", dev->name); + goto rx_exit; + } + dev = master_dev; + } + + /* + * We're only interested in IPv4 and IPv6 packets. + */ + if (likely(htons(ETH_P_IP) == skb->protocol)) { + struct in_device *in_dev; + + /* + * Does our input device support IP processing? + */ + in_dev = (struct in_device *)dev->ip_ptr; + if (unlikely(!in_dev)) { + DEBUG_TRACE("no IP processing for device: %s\n", dev->name); + goto rx_exit; + } + + /* + * Does it have an IP address? If it doesn't then we can't do anything + * interesting here! + */ + if (unlikely(!in_dev->ifa_list)) { + DEBUG_TRACE("no IP address for device: %s\n", dev->name); + goto rx_exit; + } + + ret = sfe_ipv4_recv(dev, skb); + + } else if (likely(htons(ETH_P_IPV6) == skb->protocol)) { + struct inet6_dev *in_dev; + + /* + * Does our input device support IPv6 processing? + */ + in_dev = (struct inet6_dev *)dev->ip6_ptr; + if (unlikely(!in_dev)) { + DEBUG_TRACE("no IPv6 processing for device: %s\n", dev->name); + goto rx_exit; + } + + /* + * Does it have an IPv6 address? If it doesn't then we can't do anything + * interesting here! + */ + if (unlikely(list_empty(&in_dev->addr_list))) { + DEBUG_TRACE("no IPv6 address for device: %s\n", dev->name); + goto rx_exit; + } + + ret = sfe_ipv6_recv(dev, skb); + + } else { + DEBUG_TRACE("not IP packet\n"); + } + +rx_exit: + if (master_dev) { + dev_put(master_dev); + } + + return ret; +} + +/* + * fast_classifier_find_dev_and_mac_addr() + * Find the device and MAC address for a given IPv4 address. + * + * Returns true if we find the device and MAC address, otherwise false. + * + * We look up the rtable entry for the address and, from its neighbour + * structure, obtain the hardware address. This means this function also + * works if the neighbours are routers too. + */ +static bool fast_classifier_find_dev_and_mac_addr(struct sk_buff *skb, sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, bool is_v4) +{ + struct neighbour *neigh; + struct rtable *rt; + struct rt6_info *rt6; + struct dst_entry *dst; + struct net_device *mac_dev; + + /* + * If we have skb provided, use it as the original code is unable + * to lookup routes that are policy routed. + */ + if (unlikely(skb)) { + dst = skb_dst(skb); + goto skip_dst_lookup; + } + + /* + * Look up the rtable entry for the IP address then get the hardware + * address from its neighbour structure. This means this works when the + * neighbours are routers too. + */ + if (likely(is_v4)) { + rt = ip_route_output(&init_net, addr->ip, 0, 0, 0); + if (unlikely(IS_ERR(rt))) { + goto ret_fail; + } + + dst = (struct dst_entry *)rt; + } +#ifdef SFE_SUPPORT_IPV6 + else { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0); +#else + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0); +#endif /*KERNEL_VERSION(4, 17, 0)*/ + if (!rt6) { + goto ret_fail; + } + + dst = (struct dst_entry *)rt6; + } +#endif + +skip_dst_lookup: + rcu_read_lock(); + neigh = sfe_dst_get_neighbour(dst, addr); + if (unlikely(!neigh)) { + rcu_read_unlock(); + if (likely(!skb)) + dst_release(dst); + + goto ret_fail; + } + + if (unlikely(!(neigh->nud_state & NUD_VALID))) { + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + + goto ret_fail; + } + + mac_dev = neigh->dev; + if (!mac_dev) { + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + + goto ret_fail; + } + + memcpy(mac_addr, neigh->ha, (size_t)mac_dev->addr_len); + + dev_hold(mac_dev); + *dev = mac_dev; + rcu_read_unlock(); + neigh_release(neigh); + if (likely(!skb)) + dst_release(dst); + + return true; + +ret_fail: + if (is_v4) { + DEBUG_TRACE("failed to find MAC address for IP: %pI4\n", addr); + + } else { + DEBUG_TRACE("failed to find MAC address for IP: %pI6\n", addr); + } + + return false; +} + +static DEFINE_SPINLOCK(sfe_connections_lock); + +struct sfe_connection { + struct hlist_node hl; + struct sfe_connection_create *sic; + struct nf_conn *ct; + int hits; + int offload_permit; + int offloaded; + bool is_v4; + unsigned char smac[ETH_ALEN]; + unsigned char dmac[ETH_ALEN]; +}; + +static int sfe_connections_size; + +#define FC_CONN_HASH_ORDER 13 +static DEFINE_HASHTABLE(fc_conn_ht, FC_CONN_HASH_ORDER); + +static u32 fc_conn_hash(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, + unsigned short sport, unsigned short dport, bool is_v4) +{ + u32 idx, cnt = ((is_v4 ? sizeof(saddr->ip) : sizeof(saddr->ip6))/sizeof(u32)); + u32 hash = 0; + + for (idx = 0; idx < cnt; idx++) { + hash ^= ((u32 *)saddr)[idx] ^ ((u32 *)daddr)[idx]; + } + + return hash ^ (sport | (dport << 16)); +} + +/* + * fast_classifier_update_protocol() + * Update sfe_ipv4_create struct with new protocol information before we offload + */ +static int fast_classifier_update_protocol(struct sfe_connection_create *p_sic, struct nf_conn *ct) +{ + switch (p_sic->protocol) { + case IPPROTO_TCP: + p_sic->src_td_window_scale = ct->proto.tcp.seen[0].td_scale; + p_sic->src_td_max_window = ct->proto.tcp.seen[0].td_maxwin; + p_sic->src_td_end = ct->proto.tcp.seen[0].td_end; + p_sic->src_td_max_end = ct->proto.tcp.seen[0].td_maxend; + p_sic->dest_td_window_scale = ct->proto.tcp.seen[1].td_scale; + p_sic->dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin; + p_sic->dest_td_end = ct->proto.tcp.seen[1].td_end; + p_sic->dest_td_max_end = ct->proto.tcp.seen[1].td_maxend; + + if (nf_ct_tcp_no_window_check + || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL) + || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { + p_sic->flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; + } + + /* + * If the connection is shutting down do not manage it. + * state can not be SYN_SENT, SYN_RECV because connection is assured + * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. + */ + spin_lock(&ct->lock); + if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) { + spin_unlock(&ct->lock); + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_TCP_NOT_ESTABLISHED); + DEBUG_TRACE("connection in termination state: %#x, s: %pI4:%u, d: %pI4:%u\n", + ct->proto.tcp.state, &p_sic->src_ip, ntohs(p_sic->src_port), + &p_sic->dest_ip, ntohs(p_sic->dest_port)); + return 0; + } + spin_unlock(&ct->lock); + break; + + case IPPROTO_UDP: + break; + + default: + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UNKNOW_PROTOCOL); + DEBUG_TRACE("unhandled protocol %d\n", p_sic->protocol); + return 0; + } + + return 1; +} + +/* fast_classifier_send_genl_msg() + * Function to send a generic netlink message + */ +static void fast_classifier_send_genl_msg(int msg, struct fast_classifier_tuple *fc_msg) +{ + struct sk_buff *skb; + int rc; + int buf_len; + int total_len; + void *msg_head; + + /* + * Calculate our packet payload size. + * Start with our family header. + */ + buf_len = fast_classifier_gnl_family.hdrsize; + + /* + * Add the nla_total_size of each attribute we're going to nla_put(). + */ + buf_len += nla_total_size(sizeof(*fc_msg)); + + /* + * Lastly we need to add space for the NL message header since + * genlmsg_new only accounts for the GENL header and not the + * outer NL header. To do this, we use a NL helper function which + * calculates the total size of a netlink message given a payload size. + * Note this value does not include the GENL header, but that's + * added automatically by genlmsg_new. + */ + total_len = nlmsg_total_size(buf_len); + skb = genlmsg_new(total_len, GFP_ATOMIC); + if (!skb) + return; + + msg_head = genlmsg_put(skb, 0, 0, &fast_classifier_gnl_family, 0, msg); + if (!msg_head) { + nlmsg_free(skb); + return; + } + + rc = nla_put(skb, FAST_CLASSIFIER_A_TUPLE, sizeof(struct fast_classifier_tuple), fc_msg); + if (rc != 0) { + genlmsg_cancel(skb, msg_head); + nlmsg_free(skb); + return; + } + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19 , 0)) + rc = genlmsg_end(skb, msg_head); + if (rc < 0) { + genlmsg_cancel(skb, msg_head); + nlmsg_free(skb); + return; + } +#else + genlmsg_end(skb, msg_head); + +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) + rc = genlmsg_multicast(&fast_classifier_gnl_family, skb, 0, 0, GFP_ATOMIC); +#else + rc = genlmsg_multicast(skb, 0, fast_classifier_genl_mcgrp[0].id, GFP_ATOMIC); +#endif + switch (msg) { + case FAST_CLASSIFIER_C_OFFLOADED: + if (rc == 0) { + atomic_inc(&offloaded_msgs); + } else { + atomic_inc(&offloaded_fail_msgs); + } + break; + case FAST_CLASSIFIER_C_DONE: + if (rc == 0) { + atomic_inc(&done_msgs); + } else { + atomic_inc(&done_fail_msgs); + } + break; + default: + DEBUG_ERROR("fast-classifer: Unknown message type sent!\n"); + break; + } + + DEBUG_TRACE("Notify NL message %d ", msg); + if (fc_msg->ethertype == AF_INET) { + DEBUG_TRACE("sip=%pI4 dip=%pI4 ", &fc_msg->src_saddr, &fc_msg->dst_saddr); + } else { + DEBUG_TRACE("sip=%pI6 dip=%pI6 ", &fc_msg->src_saddr, &fc_msg->dst_saddr); + } + DEBUG_TRACE("protocol=%d sport=%d dport=%d smac=%pM dmac=%pM\n", + fc_msg->proto, fc_msg->sport, fc_msg->dport, fc_msg->smac, fc_msg->dmac); +} + +/* + * fast_classifier_find_conn() + * find a connection object in the hash table + * @pre the sfe_connection_lock must be held before calling this function + */ +static struct sfe_connection * +fast_classifier_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, + unsigned short sport, unsigned short dport, + unsigned char proto, bool is_v4) +{ + struct sfe_connection_create *p_sic; + struct sfe_connection *conn; + u32 key; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) + struct hlist_node *node; +#endif + + key = fc_conn_hash(saddr, daddr, sport, dport, is_v4); + + sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { + if (conn->is_v4 != is_v4) { + continue; + } + + p_sic = conn->sic; + + if (p_sic->protocol == proto && + p_sic->src_port == sport && + p_sic->dest_port == dport && + sfe_addr_equal(&p_sic->src_ip, saddr, is_v4) && + sfe_addr_equal(&p_sic->dest_ip, daddr, is_v4)) { + return conn; + } + } + + DEBUG_TRACE("connection not found\n"); + return NULL; +} + +/* + * fast_classifier_sb_find_conn() + * find a connection object in the hash table according to information of packet + * if not found, reverse the tuple and try again. + * @pre the sfe_connection_lock must be held before calling this function + */ +static struct sfe_connection * +fast_classifier_sb_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr, + unsigned short sport, unsigned short dport, + unsigned char proto, bool is_v4) +{ + struct sfe_connection_create *p_sic; + struct sfe_connection *conn; + u32 key; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) + struct hlist_node *node; +#endif + + key = fc_conn_hash(saddr, daddr, sport, dport, is_v4); + + sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { + if (conn->is_v4 != is_v4) { + continue; + } + + p_sic = conn->sic; + + if (p_sic->protocol == proto && + p_sic->src_port == sport && + p_sic->dest_port_xlate == dport && + sfe_addr_equal(&p_sic->src_ip, saddr, is_v4) && + sfe_addr_equal(&p_sic->dest_ip_xlate, daddr, is_v4)) { + return conn; + } + } + + /* + * Reverse the tuple and try again + */ + key = fc_conn_hash(daddr, saddr, dport, sport, is_v4); + + sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) { + if (conn->is_v4 != is_v4) { + continue; + } + + p_sic = conn->sic; + + if (p_sic->protocol == proto && + p_sic->src_port == dport && + p_sic->dest_port_xlate == sport && + sfe_addr_equal(&p_sic->src_ip, daddr, is_v4) && + sfe_addr_equal(&p_sic->dest_ip_xlate, saddr, is_v4)) { + return conn; + } + } + + DEBUG_TRACE("connection not found\n"); + return NULL; +} + +/* + * fast_classifier_add_conn() + * add a connection object in the hash table if no duplicate + * @conn connection to add + * @return conn if successful, NULL if duplicate + */ +static struct sfe_connection * +fast_classifier_add_conn(struct sfe_connection *conn) +{ + struct sfe_connection_create *sic = conn->sic; + u32 key; + + spin_lock_bh(&sfe_connections_lock); + if (fast_classifier_find_conn(&sic->src_ip, &sic->dest_ip, sic->src_port, + sic->dest_port, sic->protocol, conn->is_v4)) { + spin_unlock_bh(&sfe_connections_lock); + return NULL; + } + + key = fc_conn_hash(&sic->src_ip, &sic->dest_ip, + sic->src_port, sic->dest_port, conn->is_v4); + + hash_add(fc_conn_ht, &conn->hl, key); + sfe_connections_size++; + spin_unlock_bh(&sfe_connections_lock); + + DEBUG_TRACE(" -> adding item to sfe_connections, new size: %d\n", sfe_connections_size); + + if (conn->is_v4) { + DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", + key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port); + } else { + DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", + key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port); + } + + return conn; +} + +/* + * fast_classifier_offload_genl_msg() + * Called from user space to offload a connection + */ +static int +fast_classifier_offload_genl_msg(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *na; + struct fast_classifier_tuple *fc_msg; + struct sfe_connection *conn; + + na = info->attrs[FAST_CLASSIFIER_A_TUPLE]; + fc_msg = nla_data(na); + + if (fc_msg->ethertype == AF_INET) { + DEBUG_TRACE("want to offload: %d-%d, %pI4, %pI4, %d, %d SMAC=%pM DMAC=%pM\n", + fc_msg->ethertype, + fc_msg->proto, + &fc_msg->src_saddr, + &fc_msg->dst_saddr, + fc_msg->sport, + fc_msg->dport, + fc_msg->smac, + fc_msg->dmac); + } else { + DEBUG_TRACE("want to offload: %d-%d, %pI6, %pI6, %d, %d SMAC=%pM DMAC=%pM\n", + fc_msg->ethertype, + fc_msg->proto, + &fc_msg->src_saddr, + &fc_msg->dst_saddr, + fc_msg->sport, + fc_msg->dport, + fc_msg->smac, + fc_msg->dmac); + } + + spin_lock_bh(&sfe_connections_lock); + conn = fast_classifier_sb_find_conn((sfe_ip_addr_t *)&fc_msg->src_saddr, + (sfe_ip_addr_t *)&fc_msg->dst_saddr, + fc_msg->sport, + fc_msg->dport, + fc_msg->proto, + (fc_msg->ethertype == AF_INET)); + if (!conn) { + spin_unlock_bh(&sfe_connections_lock); + DEBUG_TRACE("REQUEST OFFLOAD NO MATCH\n"); + atomic_inc(&offload_no_match_msgs); + return 0; + } + + conn->offload_permit = 1; + spin_unlock_bh(&sfe_connections_lock); + atomic_inc(&offload_msgs); + + DEBUG_TRACE("INFO: calling sfe rule creation!\n"); + return 0; +} + +/* + * fast_classifier_nl_genl_msg_DUMP() + * ignore fast_classifier_messages OFFLOADED and DONE + */ +static int fast_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, + struct netlink_callback *cb) +{ + return 0; +} + +/* auto offload connection once we have this many packets*/ +static int offload_at_pkts = 128; + +/* + * fast_classifier_post_routing() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4) +{ + int ret; + struct sfe_connection_create sic; + struct sfe_connection_create *p_sic; + struct net_device *in; + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + struct net_device *dev; + struct net_device *src_dev; + struct net_device *dest_dev; + struct net_device *src_dev_tmp; + struct net_device *dest_dev_tmp; + struct net_device *src_br_dev = NULL; + struct net_device *dest_br_dev = NULL; + struct nf_conntrack_tuple orig_tuple; + struct nf_conntrack_tuple reply_tuple; + struct sfe_connection *conn; + struct sk_buff *tmp_skb = NULL; + + /* + * Don't process broadcast or multicast packets. + */ + if (unlikely(skb->pkt_type == PACKET_BROADCAST)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_PACKET_BROADCAST); + DEBUG_TRACE("broadcast, ignoring\n"); + return NF_ACCEPT; + } + if (unlikely(skb->pkt_type == PACKET_MULTICAST)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_PACKET_MULTICAST); + DEBUG_TRACE("multicast, ignoring\n"); + return NF_ACCEPT; + } + + /* + * Don't process packets that are not being forwarded. + */ + in = dev_get_by_index(&init_net, skb->skb_iif); + if (!in) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_IIF); + DEBUG_TRACE("packet not forwarding\n"); + return NF_ACCEPT; + } + + dev_put(in); + + /* + * Don't process packets that aren't being tracked by conntrack. + */ + ct = nf_ct_get(skb, &ctinfo); + if (unlikely(!ct)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_CT); + DEBUG_TRACE("no conntrack connection, ignoring\n"); + return NF_ACCEPT; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + /* + * Don't process untracked connections. + */ + if (unlikely(nf_ct_is_untracked(ct))) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_NO_TRACK); + DEBUG_TRACE("untracked connection\n"); + return NF_ACCEPT; + } +#endif /*KERNEL_VERSION(4, 12, 0)*/ + + /* + * Unconfirmed connection may be dropped by Linux at the final step, + * So we don't process unconfirmed connections. + */ + if (!nf_ct_is_confirmed(ct)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_NO_CONFIRM); + DEBUG_TRACE("unconfirmed connection\n"); + return NF_ACCEPT; + } + + /* + * Don't process connections that require support from a 'helper' (typically a NAT ALG). + */ + if (unlikely(nfct_help(ct))) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_IS_ALG); + DEBUG_TRACE("connection has helper\n"); + return NF_ACCEPT; + } + + memset(&sic, 0, sizeof(sic)); + + /* + * Look up the details of our connection in conntrack. + * + * Note that the data we get from conntrack is for the "ORIGINAL" direction + * but our packet may actually be in the "REPLY" direction. + */ + orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + reply_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; + sic.protocol = (s32)orig_tuple.dst.protonum; + + sic.flags = 0; + + /* + * Get addressing information, non-NAT first + */ + if (likely(is_v4)) { + u32 dscp; + + sic.src_ip.ip = (__be32)orig_tuple.src.u3.ip; + sic.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; + + if (ipv4_is_multicast(sic.src_ip.ip) || ipv4_is_multicast(sic.dest_ip.ip)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_IS_IPV4_MCAST); + DEBUG_TRACE("multicast address\n"); + return NF_ACCEPT; + } + + /* + * NAT'ed addresses - note these are as seen from the 'reply' direction + * When NAT does not apply to this connection these will be identical to the above. + */ + sic.src_ip_xlate.ip = (__be32)reply_tuple.dst.u3.ip; + sic.dest_ip_xlate.ip = (__be32)reply_tuple.src.u3.ip; + + dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; + if (dscp) { + sic.dest_dscp = dscp; + sic.src_dscp = sic.dest_dscp; + sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; + } + } else { + u32 dscp; + + sic.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); + sic.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); + + if (ipv6_addr_is_multicast((struct in6_addr *)sic.src_ip.ip6) || + ipv6_addr_is_multicast((struct in6_addr *)sic.dest_ip.ip6)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_IS_IPV6_MCAST); + DEBUG_TRACE("multicast address\n"); + return NF_ACCEPT; + } + + /* + * NAT'ed addresses - note these are as seen from the 'reply' direction + * When NAT does not apply to this connection these will be identical to the above. + */ + sic.src_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.dst.u3.in6); + sic.dest_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.src.u3.in6); + + dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; + if (dscp) { + sic.dest_dscp = dscp; + sic.src_dscp = sic.dest_dscp; + sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; + } + } + + switch (sic.protocol) { + case IPPROTO_TCP: + sic.src_port = orig_tuple.src.u.tcp.port; + sic.dest_port = orig_tuple.dst.u.tcp.port; + sic.src_port_xlate = reply_tuple.dst.u.tcp.port; + sic.dest_port_xlate = reply_tuple.src.u.tcp.port; + + /* + * Don't try to manage a non-established connection. + */ + if (!test_bit(IPS_ASSURED_BIT, &ct->status)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_TCP_NOT_ASSURED); + DEBUG_TRACE("non-established connection\n"); + return NF_ACCEPT; + } + + break; + + case IPPROTO_UDP: + sic.src_port = orig_tuple.src.u.udp.port; + sic.dest_port = orig_tuple.dst.u.udp.port; + sic.src_port_xlate = reply_tuple.dst.u.udp.port; + sic.dest_port_xlate = reply_tuple.src.u.udp.port; + + /* + * Somehow, SFE is not playing nice with IPSec traffic. + * Do not accelerate for now. + */ + if (ntohs(sic.dest_port) == 4500 || ntohs(sic.dest_port) == 500) { + if (likely(is_v4)) + DEBUG_TRACE("quarkysg:: IPsec bypass: %pI4:%d(%pI4:%d) to %pI4:%d(%pI4:%d)\n", + &sic.src_ip.ip, ntohs(sic.src_port), &sic.src_ip_xlate.ip, ntohs(sic.src_port_xlate), + &sic.dest_ip.ip, ntohs(sic.dest_port), &sic.dest_ip_xlate.ip, ntohs(sic.dest_port_xlate)); + else + DEBUG_TRACE("quarkysg:: IPsec bypass: %pI6:%d to %pI6:%d\n", + &sic.src_ip.ip6, ntohs(sic.src_port), &sic.dest_ip.ip6, ntohs(sic.dest_port)); + return NF_ACCEPT; + } + break; + + default: + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UNKNOW_PROTOCOL); + DEBUG_TRACE("unhandled protocol %d\n", sic.protocol); + return NF_ACCEPT; + } + +#ifdef CONFIG_XFRM + sic.original_accel = 1; + sic.reply_accel = 1; +#endif + + /* + * Get QoS information + */ + if (skb->priority) { + sic.dest_priority = skb->priority; + sic.src_priority = sic.dest_priority; + sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY; + } + + if (is_v4) { + DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", + sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port); + } else { + DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", + sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port); + } + + /* + * If we already have this connection in our list, skip it + * XXX: this may need to be optimized + */ + spin_lock_bh(&sfe_connections_lock); + + conn = fast_classifier_find_conn(&sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port, sic.protocol, is_v4); + if (conn) { + conn->hits++; + + if (!conn->offloaded) { + if (conn->offload_permit || conn->hits >= offload_at_pkts) { + DEBUG_TRACE("OFFLOADING CONNECTION, TOO MANY HITS\n"); + + if (fast_classifier_update_protocol(conn->sic, conn->ct) == 0) { + spin_unlock_bh(&sfe_connections_lock); + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_UPDATE_PROTOCOL_FAIL); + DEBUG_TRACE("UNKNOWN PROTOCOL OR CONNECTION CLOSING, SKIPPING\n"); + return NF_ACCEPT; + } + + DEBUG_TRACE("INFO: calling sfe rule creation!\n"); + spin_unlock_bh(&sfe_connections_lock); + + ret = is_v4 ? sfe_ipv4_create_rule(conn->sic) : sfe_ipv6_create_rule(conn->sic); + if ((ret == 0) || (ret == -EADDRINUSE)) { + struct fast_classifier_tuple fc_msg; + + if (is_v4) { + fc_msg.ethertype = AF_INET; + fc_msg.src_saddr.in = *((struct in_addr *)&sic.src_ip); + fc_msg.dst_saddr.in = *((struct in_addr *)&sic.dest_ip_xlate); + } else { + fc_msg.ethertype = AF_INET6; + fc_msg.src_saddr.in6 = *((struct in6_addr *)&sic.src_ip); + fc_msg.dst_saddr.in6 = *((struct in6_addr *)&sic.dest_ip_xlate); + } + + fc_msg.proto = sic.protocol; + fc_msg.sport = sic.src_port; + fc_msg.dport = sic.dest_port_xlate; + memcpy(fc_msg.smac, conn->smac, ETH_ALEN); + memcpy(fc_msg.dmac, conn->dmac, ETH_ALEN); + fast_classifier_send_genl_msg(FAST_CLASSIFIER_C_OFFLOADED, &fc_msg); + conn->offloaded = 1; + } + + return NF_ACCEPT; + } + } + + spin_unlock_bh(&sfe_connections_lock); + if (conn->offloaded) { + is_v4 ? sfe_ipv4_update_rule(conn->sic) : sfe_ipv6_update_rule(conn->sic); + } + + DEBUG_TRACE("FOUND, SKIPPING\n"); + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_WAIT_FOR_ACCELERATION); + return NF_ACCEPT; + } + + spin_unlock_bh(&sfe_connections_lock); + + /* + * Get the net device and MAC addresses that correspond to the various source and + * destination host addresses. + */ + if (!fast_classifier_find_dev_and_mac_addr(NULL, &sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_SRC_DEV); + return NF_ACCEPT; + } + src_dev = src_dev_tmp; + + if (!fast_classifier_find_dev_and_mac_addr(NULL, &sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_SRC_XLATE_DEV); + goto done1; + } + dev_put(dev); + + if (unlikely(!is_v4)) + tmp_skb = skb; + + if (!fast_classifier_find_dev_and_mac_addr(tmp_skb, &sic.dest_ip, &dev, sic.dest_mac, is_v4)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_DEST_DEV); + goto done1; + } + dev_put(dev); + + if (!fast_classifier_find_dev_and_mac_addr(skb, &sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_DEST_XLATE_DEV); + goto done1; + } + dest_dev = dest_dev_tmp; + + /* + * Our devices may actually be part of a bridge interface. If that's + * the case then find the bridge interface instead. + */ + if (src_dev->priv_flags & IFF_BRIDGE_PORT) { + src_br_dev = sfe_dev_get_master(src_dev); + if (!src_br_dev) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_BRIDGE); + DEBUG_TRACE("no bridge found for: %s\n", src_dev->name); + goto done2; + } + src_dev = src_br_dev; + } + + if (dest_dev->priv_flags & IFF_BRIDGE_PORT) { + dest_br_dev = sfe_dev_get_master(dest_dev); + if (!dest_br_dev) { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_BRIDGE); + DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name); + goto done3; + } + dest_dev = dest_br_dev; + } + + sic.src_dev = src_dev; + sic.dest_dev = dest_dev; + + sic.src_mtu = src_dev->mtu; + sic.dest_mtu = dest_dev->mtu; + + if (skb->mark) { + DEBUG_TRACE("SKB MARK NON ZERO %x\n", skb->mark); + } + sic.mark = skb->mark; + + conn = kmalloc(sizeof(*conn), GFP_ATOMIC); + if (!conn) { + printk(KERN_CRIT "ERROR: no memory for sfe\n"); + goto done4; + } + conn->hits = 0; + conn->offload_permit = 0; + conn->offloaded = 0; + conn->is_v4 = is_v4; + DEBUG_TRACE("Source MAC=%pM\n", sic.src_mac); + memcpy(conn->smac, sic.src_mac, ETH_ALEN); + memcpy(conn->dmac, sic.dest_mac_xlate, ETH_ALEN); + + p_sic = kmalloc(sizeof(*p_sic), GFP_ATOMIC); + if (!p_sic) { + printk(KERN_CRIT "ERROR: no memory for sfe\n"); + kfree(conn); + goto done4; + } + + memcpy(p_sic, &sic, sizeof(sic)); + conn->sic = p_sic; + conn->ct = ct; + + if (!fast_classifier_add_conn(conn)) { + kfree(conn->sic); + kfree(conn); + } + + /* + * If we had bridge ports then release them too. + */ +done4: + if (dest_br_dev) { + dev_put(dest_br_dev); + } +done3: + if (src_br_dev) { + dev_put(src_br_dev); + } +done2: + dev_put(dest_dev_tmp); +done1: + dev_put(src_dev_tmp); + + return NF_ACCEPT; +} + +/* + * fast_classifier_ipv4_post_routing_hook() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +fast_classifier_ipv4_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) +{ + return fast_classifier_post_routing(skb, true); +} + +/* + * fast_classifier_ipv6_post_routing_hook() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +fast_classifier_ipv6_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) +{ + return fast_classifier_post_routing(skb, false); +} + +/* + * fast_classifier_update_mark() + * updates the mark for a fast-classifier connection + */ +static void fast_classifier_update_mark(struct sfe_connection_mark *mark, bool is_v4) +{ + struct sfe_connection *conn; + + spin_lock_bh(&sfe_connections_lock); + + conn = fast_classifier_find_conn(&mark->src_ip, &mark->dest_ip, + mark->src_port, mark->dest_port, + mark->protocol, is_v4); + if (conn) { + conn->sic->mark = mark->mark; + } + + spin_unlock_bh(&sfe_connections_lock); +} + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +/* + * fast_classifier_conntrack_event() + * Callback event invoked when a conntrack connection's state changes. + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +static int fast_classifier_conntrack_event(struct notifier_block *this, + unsigned long events, void *ptr) +#else +static int fast_classifier_conntrack_event(unsigned int events, struct nf_ct_event *item) +#endif +{ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + struct nf_ct_event *item = ptr; +#endif + struct sfe_connection_destroy sid; + struct nf_conn *ct = item->ct; + struct nf_conntrack_tuple orig_tuple; + struct sfe_connection *conn; + struct fast_classifier_tuple fc_msg; + int offloaded = 0; + bool is_v4; + + /* + * If we don't have a conntrack entry then we're done. + */ + if (unlikely(!ct)) { + DEBUG_WARN("no ct in conntrack event callback\n"); + return NOTIFY_DONE; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + /* + * If this is an untracked connection then we can't have any state either. + */ + if (unlikely(nf_ct_is_untracked(ct))) { + DEBUG_TRACE("ignoring untracked conn\n"); + return NOTIFY_DONE; + } +#endif /*KERNEL_VERSION(4, 12, 0)*/ + + orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + sid.protocol = (s32)orig_tuple.dst.protonum; + + /* + * Extract information from the conntrack connection. We're only interested + * in nominal connection information (i.e. we're ignoring any NAT information). + */ + if (likely(nf_ct_l3num(ct) == AF_INET)) { + sid.src_ip.ip = (__be32)orig_tuple.src.u3.ip; + sid.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; + is_v4 = true; + } else if (likely(nf_ct_l3num(ct) == AF_INET6)) { + sid.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); + sid.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); + is_v4 = false; + } else { + DEBUG_TRACE("ignoring non-IPv4 and non-IPv6 connection\n"); + return NOTIFY_DONE; + } + + switch (sid.protocol) { + case IPPROTO_TCP: + sid.src_port = orig_tuple.src.u.tcp.port; + sid.dest_port = orig_tuple.dst.u.tcp.port; + break; + + case IPPROTO_UDP: + sid.src_port = orig_tuple.src.u.udp.port; + sid.dest_port = orig_tuple.dst.u.udp.port; + break; + + default: + DEBUG_TRACE("unhandled protocol: %d\n", sid.protocol); + return NOTIFY_DONE; + } + + /* + * Check for an updated mark + */ + if ((events & (1 << IPCT_MARK)) && (ct->mark != 0)) { + struct sfe_connection_mark mark; + + mark.protocol = sid.protocol; + mark.src_ip = sid.src_ip; + mark.dest_ip = sid.dest_ip; + mark.src_port = sid.src_port; + mark.dest_port = sid.dest_port; + mark.mark = ct->mark; + + is_v4 ? sfe_ipv4_mark_rule(&mark) : sfe_ipv6_mark_rule(&mark); + fast_classifier_update_mark(&mark, is_v4); + } + + /* + * We're only interested in destroy events at this point + */ + if (unlikely(!(events & (1 << IPCT_DESTROY)))) { + DEBUG_TRACE("ignoring non-destroy event\n"); + return NOTIFY_DONE; + } + + if (is_v4) { + DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n", + sid.protocol, &sid.src_ip, &sid.dest_ip, ntohs(sid.src_port), ntohs(sid.dest_port)); + } else { + DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n", + sid.protocol, &sid.src_ip, &sid.dest_ip, ntohs(sid.src_port), ntohs(sid.dest_port)); + } + + spin_lock_bh(&sfe_connections_lock); + + conn = fast_classifier_find_conn(&sid.src_ip, &sid.dest_ip, sid.src_port, sid.dest_port, sid.protocol, is_v4); + if (conn && conn->offloaded) { + if (is_v4) { + fc_msg.ethertype = AF_INET; + fc_msg.src_saddr.in = *((struct in_addr *)&conn->sic->src_ip); + fc_msg.dst_saddr.in = *((struct in_addr *)&conn->sic->dest_ip_xlate); + } else { + fc_msg.ethertype = AF_INET6; + fc_msg.src_saddr.in6 = *((struct in6_addr *)&conn->sic->src_ip); + fc_msg.dst_saddr.in6 = *((struct in6_addr *)&conn->sic->dest_ip_xlate); + } + + fc_msg.proto = conn->sic->protocol; + fc_msg.sport = conn->sic->src_port; + fc_msg.dport = conn->sic->dest_port_xlate; + memcpy(fc_msg.smac, conn->smac, ETH_ALEN); + memcpy(fc_msg.dmac, conn->dmac, ETH_ALEN); + offloaded = 1; + } + + if (conn) { + DEBUG_TRACE("Free connection\n"); + + hash_del(&conn->hl); + sfe_connections_size--; + kfree(conn->sic); + kfree(conn); + } else { + fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_CT_DESTROY_MISS); + } + + spin_unlock_bh(&sfe_connections_lock); + + is_v4 ? sfe_ipv4_destroy_rule(&sid) : sfe_ipv6_destroy_rule(&sid); + + if (offloaded) { + fast_classifier_send_genl_msg(FAST_CLASSIFIER_C_DONE, &fc_msg); + } + + return NOTIFY_DONE; +} + +/* + * Netfilter conntrack event system to monitor connection tracking changes + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +static struct notifier_block fast_classifier_conntrack_notifier = { + .notifier_call = fast_classifier_conntrack_event, +}; +#else +static struct nf_ct_event_notifier fast_classifier_conntrack_notifier = { + .fcn = fast_classifier_conntrack_event, +}; +#endif +#endif + +/* + * Structure to establish a hook into the post routing netfilter point - this + * will pick up local outbound and packets going from one interface to another. + * + * Note: see include/linux/netfilter_ipv4.h for info related to priority levels. + * We want to examine packets after NAT translation and any ALG processing. + */ +static struct nf_hook_ops fast_classifier_ops_post_routing[] __read_mostly = { + SFE_IPV4_NF_POST_ROUTING_HOOK(__fast_classifier_ipv4_post_routing_hook), + SFE_IPV6_NF_POST_ROUTING_HOOK(__fast_classifier_ipv6_post_routing_hook), +}; + +/* + * fast_classifier_sync_rule() + * Synchronize a connection's state. + */ +static void fast_classifier_sync_rule(struct sfe_connection_sync *sis) +{ + struct nf_conntrack_tuple_hash *h; + struct nf_conntrack_tuple tuple; + struct nf_conn *ct; + SFE_NF_CONN_ACCT(acct); + + /* + * Create a tuple so as to be able to look up a connection + */ + memset(&tuple, 0, sizeof(tuple)); + tuple.src.u.all = (__be16)sis->src_port; + tuple.dst.dir = IP_CT_DIR_ORIGINAL; + tuple.dst.protonum = (u8)sis->protocol; + tuple.dst.u.all = (__be16)sis->dest_port; + + if (sis->is_v6) { + tuple.src.u3.in6 = *((struct in6_addr *)sis->src_ip.ip6); + tuple.dst.u3.in6 = *((struct in6_addr *)sis->dest_ip.ip6); + tuple.src.l3num = AF_INET6; + + DEBUG_TRACE("update connection - p: %d, s: %pI6:%u, d: %pI6:%u\n", + (int)tuple.dst.protonum, + &tuple.src.u3.in6, (unsigned int)ntohs(tuple.src.u.all), + &tuple.dst.u3.in6, (unsigned int)ntohs(tuple.dst.u.all)); + } else { + tuple.src.u3.ip = sis->src_ip.ip; + tuple.dst.u3.ip = sis->dest_ip.ip; + tuple.src.l3num = AF_INET; + + DEBUG_TRACE("update connection - p: %d, s: %pI4:%u, d: %pI4:%u\n", + (int)tuple.dst.protonum, + &tuple.src.u3.ip, (unsigned int)ntohs(tuple.src.u.all), + &tuple.dst.u3.ip, (unsigned int)ntohs(tuple.dst.u.all)); + } + + /* + * Update packet count for ingress on bridge device + */ + if (skip_to_bridge_ingress) { + struct rtnl_link_stats64 nlstats; + nlstats.tx_packets = 0; + nlstats.tx_bytes = 0; + + if (sis->src_dev && IFF_EBRIDGE && + (sis->src_new_packet_count || sis->src_new_byte_count)) { + nlstats.rx_packets = sis->src_new_packet_count; + nlstats.rx_bytes = sis->src_new_byte_count; + spin_lock_bh(&sfe_connections_lock); + br_dev_update_stats(sis->src_dev, &nlstats); + spin_unlock_bh(&sfe_connections_lock); + } + if (sis->dest_dev && IFF_EBRIDGE && + (sis->dest_new_packet_count || sis->dest_new_byte_count)) { + nlstats.rx_packets = sis->dest_new_packet_count; + nlstats.rx_bytes = sis->dest_new_byte_count; + spin_lock_bh(&sfe_connections_lock); + br_dev_update_stats(sis->dest_dev, &nlstats); + spin_unlock_bh(&sfe_connections_lock); + } + } + + /* + * Look up conntrack connection + */ + h = nf_conntrack_find_get(&init_net, SFE_NF_CT_DEFAULT_ZONE, &tuple); + if (unlikely(!h)) { + DEBUG_TRACE("no connection found\n"); + return; + } + + ct = nf_ct_tuplehash_to_ctrack(h); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) + NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); +#endif /*KERNEL_VERSION(4, 9, 0)*/ + + /* + * Only update if this is not a fixed timeout + */ + if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { + spin_lock_bh(&ct->lock); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + ct->timeout += sis->delta_jiffies; +#else + ct->timeout.expires += sis->delta_jiffies; +#endif /*KERNEL_VERSION(4, 9, 0)*/ + spin_unlock_bh(&ct->lock); + } + + acct = nf_conn_acct_find(ct); + if (acct) { + spin_lock_bh(&ct->lock); + atomic64_add(sis->src_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].packets); + atomic64_add(sis->src_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].bytes); + atomic64_add(sis->dest_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); + atomic64_add(sis->dest_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].bytes); + spin_unlock_bh(&ct->lock); + } + + switch (sis->protocol) { + case IPPROTO_TCP: + spin_lock_bh(&ct->lock); + if (ct->proto.tcp.seen[0].td_maxwin < sis->src_td_max_window) { + ct->proto.tcp.seen[0].td_maxwin = sis->src_td_max_window; + } + if ((s32)(ct->proto.tcp.seen[0].td_end - sis->src_td_end) < 0) { + ct->proto.tcp.seen[0].td_end = sis->src_td_end; + } + if ((s32)(ct->proto.tcp.seen[0].td_maxend - sis->src_td_max_end) < 0) { + ct->proto.tcp.seen[0].td_maxend = sis->src_td_max_end; + } + if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) { + ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window; + } + if ((s32)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) { + ct->proto.tcp.seen[1].td_end = sis->dest_td_end; + } + if ((s32)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) { + ct->proto.tcp.seen[1].td_maxend = sis->dest_td_max_end; + } + spin_unlock_bh(&ct->lock); + break; + } + + /* + * Release connection + */ + nf_ct_put(ct); +} + +/* + * fast_classifier_device_event() + */ +static int fast_classifier_device_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = SFE_DEV_EVENT_PTR(ptr); + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv4_destroy_all_rules_for_dev(dev); + sfe_ipv6_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * fast_classifier_inet_event() + */ +static int fast_classifier_inet_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv4_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * fast_classifier_inet6_event() + */ +static int fast_classifier_inet6_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ((struct inet6_ifaddr *)ptr)->idev->dev; + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv6_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * fast_classifier_get_offload_at_pkts() + */ +static ssize_t fast_classifier_get_offload_at_pkts(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", offload_at_pkts); +} + +/* + * fast_classifier_set_offload_at_pkts() + */ +static ssize_t fast_classifier_set_offload_at_pkts(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + long new; + int ret; + + ret = kstrtol(buf, 0, &new); + if (ret == -EINVAL || ((int)new != new)) + return -EINVAL; + + offload_at_pkts = new; + + return size; +} + +/* + * fast_classifier_get_debug_info() + */ +static ssize_t fast_classifier_get_debug_info(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + size_t len = 0; + struct sfe_connection *conn; + u32 i; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) + struct hlist_node *node; +#endif + + spin_lock_bh(&sfe_connections_lock); + len += scnprintf(buf, PAGE_SIZE - len, "size=%d offload=%d offload_no_match=%d" + " offloaded=%d done=%d offloaded_fail=%d done_fail=%d\n", + sfe_connections_size, + atomic_read(&offload_msgs), + atomic_read(&offload_no_match_msgs), + atomic_read(&offloaded_msgs), + atomic_read(&done_msgs), + atomic_read(&offloaded_fail_msgs), + atomic_read(&done_fail_msgs)); + sfe_hash_for_each(fc_conn_ht, i, node, conn, hl) { + len += scnprintf(buf + len, PAGE_SIZE - len, + (conn->is_v4 ? "o=%d, p=%d [%pM]:%pI4:%u %pI4:%u:[%pM] m=%08x h=%d\n" : "o=%d, p=%d [%pM]:%pI6:%u %pI6:%u:[%pM] m=%08x h=%d\n"), + conn->offloaded, + conn->sic->protocol, + conn->sic->src_mac, + &conn->sic->src_ip, + ntohs(conn->sic->src_port), + &conn->sic->dest_ip, + ntohs(conn->sic->dest_port), + conn->sic->dest_mac_xlate, + conn->sic->mark, + conn->hits); + } + spin_unlock_bh(&sfe_connections_lock); + + return len; +} + +/* + * fast_classifier_get_skip_bridge_ingress() + */ +static ssize_t fast_classifier_get_skip_bridge_ingress(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", skip_to_bridge_ingress); +} + +/* + * fast_classifier_set_skip_bridge_ingress() + */ +static ssize_t fast_classifier_set_skip_bridge_ingress(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + long new; + int ret; + + ret = kstrtol(buf, 0, &new); + if (ret == -EINVAL || ((int)new != new)) + return -EINVAL; + + skip_to_bridge_ingress = new ? 1 : 0; + + return size; +} + +/* + * fast_classifier_get_exceptions + * dump exception counters + */ +static ssize_t fast_classifier_get_exceptions(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int idx, len; + struct fast_classifier *sc = &__sc; + + spin_lock_bh(&sc->lock); + for (len = 0, idx = 0; idx < FAST_CL_EXCEPTION_MAX; idx++) { + if (sc->exceptions[idx]) { + len += snprintf(buf + len, (ssize_t)(PAGE_SIZE - len), "%s = %d\n", fast_classifier_exception_events_string[idx], sc->exceptions[idx]); + } + } + spin_unlock_bh(&sc->lock); + + return len; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute fast_classifier_offload_at_pkts_attr = + __ATTR(offload_at_pkts, S_IWUSR | S_IRUGO, fast_classifier_get_offload_at_pkts, fast_classifier_set_offload_at_pkts); +static const struct device_attribute fast_classifier_debug_info_attr = + __ATTR(debug_info, S_IRUGO, fast_classifier_get_debug_info, NULL); +static const struct device_attribute fast_classifier_skip_bridge_ingress = + __ATTR(skip_to_bridge_ingress, S_IWUSR | S_IRUGO, fast_classifier_get_skip_bridge_ingress, fast_classifier_set_skip_bridge_ingress); +static const struct device_attribute fast_classifier_exceptions_attr = + __ATTR(exceptions, S_IRUGO, fast_classifier_get_exceptions, NULL); + +/* + * fast_classifier_init() + */ +static int __init fast_classifier_init(void) +{ + struct fast_classifier *sc = &__sc; + int result = -1; + + printk(KERN_ALERT "fast-classifier (PBR safe v2.1.4a): starting up\n"); + DEBUG_INFO("SFE CM init\n"); + + hash_init(fc_conn_ht); + + /* + * Create sys/fast_classifier + */ + sc->sys_fast_classifier = kobject_create_and_add("fast_classifier", NULL); + if (!sc->sys_fast_classifier) { + DEBUG_ERROR("failed to register fast_classifier\n"); + goto exit1; + } + + result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + if (result) { + DEBUG_ERROR("failed to register offload at pkgs: %d\n", result); + goto exit2; + } + + result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); + if (result) { + DEBUG_ERROR("failed to register debug dev: %d\n", result); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + goto exit2; + } + + result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); + if (result) { + DEBUG_ERROR("failed to register skip bridge on ingress: %d\n", result); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); + goto exit2; + } + + result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_exceptions_attr.attr); + if (result) { + DEBUG_ERROR("failed to register exceptions file: %d\n", result); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); + goto exit2; + } + + sc->dev_notifier.notifier_call = fast_classifier_device_event; + sc->dev_notifier.priority = 1; + register_netdevice_notifier(&sc->dev_notifier); + + sc->inet_notifier.notifier_call = fast_classifier_inet_event; + sc->inet_notifier.priority = 1; + register_inetaddr_notifier(&sc->inet_notifier); + + sc->inet6_notifier.notifier_call = fast_classifier_inet6_event; + sc->inet6_notifier.priority = 1; + register_inet6addr_notifier(&sc->inet6_notifier); + + /* + * Register our netfilter hooks. + */ + result = nf_register_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); + if (result < 0) { + DEBUG_ERROR("can't register nf post routing hook: %d\n", result); + goto exit3; + } + + /* + * Register a notifier hook to get fast notifications of expired connections. + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + result = nf_conntrack_register_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); +#else + result = nf_conntrack_register_notifier(&init_net, &fast_classifier_conntrack_notifier); + if (result < 0) { + DEBUG_ERROR("can't register nf notifier hook: %d\n", result); + goto exit4; + } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) + result = genl_register_family(&fast_classifier_gnl_family); + if (result) { + DEBUG_ERROR("failed to register genl family: %d\n", result); + goto exit5; + } +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) + result = genl_register_family_with_ops_groups(&fast_classifier_gnl_family, + fast_classifier_gnl_ops, + fast_classifier_genl_mcgrp); + if (result) { + DEBUG_ERROR("failed to register genl ops: %d\n", result); + goto exit5; + } +#else + result = genl_register_family(&fast_classifier_gnl_family); + if (result) { + printk(KERN_CRIT "unable to register genl family\n"); + goto exit5; + } + + result = genl_register_ops(&fast_classifier_gnl_family, fast_classifier_gnl_ops); + if (result) { + printk(KERN_CRIT "unable to register ops\n"); + goto exit6; + } + + result = genl_register_mc_group(&fast_classifier_gnl_family, + fast_classifier_genl_mcgrp); + if (result) { + printk(KERN_CRIT "unable to register multicast group\n"); + goto exit6; + } +#endif + + printk(KERN_ALERT "fast-classifier: registered\n"); + + spin_lock_init(&sc->lock); + + /* + * Hook the receive path in the network stack. + */ + BUG_ON(athrs_fast_nat_recv); + RCU_INIT_POINTER(athrs_fast_nat_recv, fast_classifier_recv); + + /* + * Hook the shortcut sync callback. + */ + sfe_ipv4_register_sync_rule_callback(fast_classifier_sync_rule); + sfe_ipv6_register_sync_rule_callback(fast_classifier_sync_rule); + return 0; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) +exit6: + genl_unregister_family(&fast_classifier_gnl_family); +#endif + +exit5: +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + nf_conntrack_unregister_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); +#else + nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier); +#endif + +exit4: +#endif + nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); + +exit3: + unregister_inetaddr_notifier(&sc->inet_notifier); + unregister_inet6addr_notifier(&sc->inet6_notifier); + unregister_netdevice_notifier(&sc->dev_notifier); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr); + sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_exceptions_attr.attr); + +exit2: + kobject_put(sc->sys_fast_classifier); + +exit1: + return result; +} + +/* + * fast_classifier_exit() + */ +static void __exit fast_classifier_exit(void) +{ + struct fast_classifier *sc = &__sc; + int result = -1; + + DEBUG_INFO("SFE CM exit\n"); + printk(KERN_ALERT "fast-classifier: shutting down\n"); + + /* + * Unregister our sync callback. + */ + sfe_ipv4_register_sync_rule_callback(NULL); + sfe_ipv6_register_sync_rule_callback(NULL); + + /* + * Unregister our receive callback. + */ + RCU_INIT_POINTER(athrs_fast_nat_recv, NULL); + + /* + * Wait for all callbacks to complete. + */ + rcu_barrier(); + + /* + * Destroy all connections. + */ + sfe_ipv4_destroy_all_rules_for_dev(NULL); + sfe_ipv6_destroy_all_rules_for_dev(NULL); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) + result = genl_unregister_ops(&fast_classifier_gnl_family, fast_classifier_gnl_ops); + if (result != 0) { + printk(KERN_CRIT "Unable to unreigster genl_ops\n"); + } +#endif + + result = genl_unregister_family(&fast_classifier_gnl_family); + if (result != 0) { + printk(KERN_CRIT "Unable to unregister genl_family\n"); + } + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + nf_conntrack_unregister_chain_notifier(&init_net, &fast_classifier_conntrack_notifier); +#else + nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier); +#endif +#endif + nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing)); + + unregister_inet6addr_notifier(&sc->inet6_notifier); + unregister_inetaddr_notifier(&sc->inet_notifier); + unregister_netdevice_notifier(&sc->dev_notifier); + + kobject_put(sc->sys_fast_classifier); +} + +module_init(fast_classifier_init) +module_exit(fast_classifier_exit) + +MODULE_DESCRIPTION("Shortcut Forwarding Engine - Connection Manager"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fast-classifier/src/fast-classifier.h b/fast-classifier/src/fast-classifier.h new file mode 100644 index 000000000..6b7a18cf6 --- /dev/null +++ b/fast-classifier/src/fast-classifier.h @@ -0,0 +1,57 @@ +/* + * User space header to send message to the fast classifier + * + * Copyright (c) 2013,2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#define FAST_CLASSIFIER_GENL_VERSION (1) +#define FAST_CLASSIFIER_GENL_NAME "FC" +#define FAST_CLASSIFIER_GENL_MCGRP "FC_MCGRP" +#define FAST_CLASSIFIER_GENL_HDRSIZE (0) + +enum { + FAST_CLASSIFIER_A_UNSPEC, + FAST_CLASSIFIER_A_TUPLE, + __FAST_CLASSIFIER_A_MAX, +}; + +#define FAST_CLASSIFIER_A_MAX (__FAST_CLASSIFIER_A_MAX - 1) + +enum { + FAST_CLASSIFIER_C_UNSPEC, + FAST_CLASSIFIER_C_OFFLOAD, + FAST_CLASSIFIER_C_OFFLOADED, + FAST_CLASSIFIER_C_DONE, + __FAST_CLASSIFIER_C_MAX, +}; + +#define FAST_CLASSIFIER_C_MAX (__FAST_CLASSIFIER_C_MAX - 1) + +struct fast_classifier_tuple { + unsigned short ethertype; + unsigned char proto; + union { + struct in_addr in; + struct in6_addr in6; + } src_saddr; + union { + struct in_addr in; + struct in6_addr in6; + } dst_saddr; + unsigned short sport; + unsigned short dport; + unsigned char smac[ETH_ALEN]; + unsigned char dmac[ETH_ALEN]; +}; diff --git a/fast-classifier/src/nl_classifier_test.c b/fast-classifier/src/nl_classifier_test.c new file mode 100644 index 000000000..639417964 --- /dev/null +++ b/fast-classifier/src/nl_classifier_test.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#define NL_CLASSIFIER_GENL_VERSION 1 +#define NL_CLASSIFIER_GENL_FAMILY "FC" +#define NL_CLASSIFIER_GENL_GROUP "FC_MCGRP" +#define NL_CLASSIFIER_GENL_HDRSIZE 0 + +enum NL_CLASSIFIER_CMD { + NL_CLASSIFIER_CMD_UNSPEC, + NL_CLASSIFIER_CMD_ACCEL, + NL_CLASSIFIER_CMD_ACCEL_OK, + NL_CLASSIFIER_CMD_CONNECTION_CLOSED, + NL_CLASSIFIER_CMD_MAX, +}; + +enum NL_CLASSIFIER_ATTR { + NL_CLASSIFIER_ATTR_UNSPEC, + NL_CLASSIFIER_ATTR_TUPLE, + NL_CLASSIFIER_ATTR_MAX, +}; + +union nl_classifier_tuple_ip { + struct in_addr in; + struct in6_addr in6; +}; + +struct nl_classifier_tuple { + unsigned short af; + unsigned char proto; + union nl_classifier_tuple_ip src_ip; + union nl_classifier_tuple_ip dst_ip; + unsigned short sport; + unsigned short dport; + unsigned char smac[6]; + unsigned char dmac[6]; +}; + +struct nl_classifier_instance { + struct nl_sock *sock; + int family_id; + int group_id; + int stop; +}; + +struct nl_classifier_instance nl_cls_inst; + +static struct nla_policy nl_classifier_genl_policy[(NL_CLASSIFIER_ATTR_MAX+1)] = { + [NL_CLASSIFIER_ATTR_TUPLE] = { .type = NLA_UNSPEC }, +}; + +void nl_classifier_dump_nl_tuple(struct nl_classifier_tuple *tuple) +{ + char ip_str[64]; + + printf("protocol = %s\n", (tuple->proto == IPPROTO_UDP) ? "udp" : ((tuple->proto == IPPROTO_TCP) ? "tcp" : "unknown")); + printf("source ip = %s\n", inet_ntop(tuple->af, &tuple->src_ip, ip_str, sizeof(ip_str))); + printf("destination ip = %s\n", inet_ntop(tuple->af, &tuple->dst_ip, ip_str, sizeof(ip_str))); + printf("source port = %d\n", ntohs(tuple->sport)); + printf("destination port = %d\n", ntohs(tuple->dport)); +} + +int nl_classifier_msg_recv(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *gnlh = nlmsg_data(nlh); + struct nlattr *attrs[(NL_CLASSIFIER_ATTR_MAX+1)]; + + genlmsg_parse(nlh, NL_CLASSIFIER_GENL_HDRSIZE, attrs, NL_CLASSIFIER_ATTR_MAX, nl_classifier_genl_policy); + + switch (gnlh->cmd) { + case NL_CLASSIFIER_CMD_ACCEL_OK: + printf("Acceleration successful:\n"); + nl_classifier_dump_nl_tuple(nla_data(attrs[NL_CLASSIFIER_ATTR_TUPLE])); + return NL_OK; + case NL_CLASSIFIER_CMD_CONNECTION_CLOSED: + printf("Connection is closed:\n"); + nl_classifier_dump_nl_tuple(nla_data(attrs[NL_CLASSIFIER_ATTR_TUPLE])); + return NL_OK; + default: + printf("nl classifier received unknow message %d\n", gnlh->cmd); + } + + return NL_SKIP; +} + +void nl_classifier_offload(struct nl_classifier_instance *inst, + unsigned char proto, unsigned long *src_saddr, + unsigned long *dst_saddr, unsigned short sport, + unsigned short dport, int af) +{ + struct nl_msg *msg; + int ret; + struct nl_classifier_tuple classifier_msg; + + memset(&classifier_msg, 0, sizeof(classifier_msg)); + classifier_msg.af = af; + classifier_msg.proto = proto; + memcpy(&classifier_msg.src_ip, src_saddr, (af == AF_INET ? 4 : 16)); + memcpy(&classifier_msg.dst_ip, dst_saddr, (af == AF_INET ? 4 : 16)); + classifier_msg.sport = sport; + classifier_msg.dport = dport; + + msg = nlmsg_alloc(); + if (!msg) { + printf("Unable to allocate message\n"); + return; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, inst->family_id, + NL_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST, + NL_CLASSIFIER_CMD_ACCEL, NL_CLASSIFIER_GENL_VERSION); + nla_put(msg, NL_CLASSIFIER_ATTR_TUPLE, sizeof(classifier_msg), &classifier_msg); + + ret = nl_send_auto(inst->sock, msg); + if (ret < 0) { + printf("send netlink message failed.\n"); + nlmsg_free(msg); + return; + } + + nlmsg_free(msg); + printf("nl classifier offload connection successful\n"); +} + +int nl_classifier_init(struct nl_classifier_instance *inst) +{ + int ret; + + inst->sock = nl_socket_alloc(); + if (!inst->sock) { + printf("Unable to allocation socket.\n"); + return -1; + } + genl_connect(inst->sock); + + inst->family_id = genl_ctrl_resolve(inst->sock, NL_CLASSIFIER_GENL_FAMILY); + if (inst->family_id < 0) { + printf("Unable to resolve family %s\n", NL_CLASSIFIER_GENL_FAMILY); + goto init_failed; + } + + inst->group_id = genl_ctrl_resolve_grp(inst->sock, NL_CLASSIFIER_GENL_FAMILY, NL_CLASSIFIER_GENL_GROUP); + if (inst->group_id < 0) { + printf("Unable to resolve mcast group %s\n", NL_CLASSIFIER_GENL_GROUP); + goto init_failed; + } + + ret = nl_socket_add_membership(inst->sock, inst->group_id); + if (ret < 0) { + printf("Unable to add membership\n"); + goto init_failed; + } + + nl_socket_disable_seq_check(inst->sock); + nl_socket_modify_cb(inst->sock, NL_CB_VALID, NL_CB_CUSTOM, nl_classifier_msg_recv, NULL); + + printf("nl classifier init successful\n"); + return 0; + +init_failed: + if (inst->sock) { + nl_close(inst->sock); + nl_socket_free(inst->sock); + inst->sock = NULL; + } + return -1; +} + +void nl_classifier_exit(struct nl_classifier_instance *inst) +{ + if (inst->sock) { + nl_close(inst->sock); + nl_socket_free(inst->sock); + inst->sock = NULL; + } + printf("nl classifier exit successful\n"); +} + +int nl_classifier_parse_arg(int argc, char *argv[], unsigned char *proto, unsigned long *src_saddr, + unsigned long *dst_saddr, unsigned short *sport, unsigned short *dport, int *af) +{ + int ret; + unsigned short port; + + if (argc < 7) { + printf("help: nl_classifier \n"); + return -1; + } + + if (0 == strncmp(argv[1], "v4", 2)) { + *af = AF_INET; + } else if (0 == strncmp(argv[1], "v6", 2)) { + *af = AF_INET6; + } else { + printf("Address family is not supported"); + return -1; + } + + if (0 == strncmp(argv[2], "udp", 3)) { + *proto = IPPROTO_UDP; + } else if (0 == strncmp(argv[2], "tcp", 3)) { + *proto = IPPROTO_TCP; + } else { + printf("Protocol is not supported"); + return -1; + } + + ret = inet_pton(*af, argv[3], src_saddr); + if (ret <= 0) { + printf("source ip has wrong format\n"); + return -1; + } + + ret = inet_pton(*af, argv[4], dst_saddr); + if (ret <= 0) { + printf("destination ip has wrong format\n"); + return -1; + } + + port = strtol(argv[5], NULL, 0); + *sport = htons(port); + port = strtol(argv[6], NULL, 0); + *dport = htons(port); + + printf("nl classifier parse arguments successful\n"); + return 0; +} + +int main(int argc, char *argv[]) +{ + struct nl_classifier_instance *inst = &nl_cls_inst; + unsigned char proto; + unsigned long src_addr[4]; + unsigned long dst_addr[4]; + unsigned short sport; + unsigned short dport; + int af; + int ret; + + ret = nl_classifier_parse_arg(argc, argv, &proto, src_addr, dst_addr, &sport, &dport, &af); + if (ret < 0) { + printf("Failed to parse arguments\n"); + return ret; + } + + ret = nl_classifier_init(inst); + if (ret < 0) { + printf("Unable to init generic netlink\n"); + return ret; + } + + nl_classifier_offload(inst, proto, src_addr, dst_addr, sport, dport, af); + + /* main loop to listen on message */ + while (!inst->stop) { + nl_recvmsgs_default(inst->sock); + } + + nl_classifier_exit(inst); + + return 0; +} diff --git a/fast-classifier/src/sfe.h b/fast-classifier/src/sfe.h new file mode 100644 index 000000000..279e7b3dc --- /dev/null +++ b/fast-classifier/src/sfe.h @@ -0,0 +1,114 @@ +/* + * sfe.h + * Shortcut forwarding engine. + * + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * The following are debug macros used throughout the SFE. + * + * The DEBUG_LEVEL enables the followings based on its value, + * when dynamic debug option is disabled. + * + * 0 = OFF + * 1 = ASSERTS / ERRORS + * 2 = 1 + WARN + * 3 = 2 + INFO + * 4 = 3 + TRACE + */ +#define DEBUG_LEVEL 2 + +#if (DEBUG_LEVEL < 1) +#define DEBUG_ASSERT(s, ...) +#define DEBUG_ERROR(s, ...) +#else +#define DEBUG_ASSERT(c, s, ...) if (!(c)) { pr_emerg("ASSERT: %s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); BUG(); } +#define DEBUG_ERROR(s, ...) pr_err("%s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if defined(CONFIG_DYNAMIC_DEBUG) +/* + * Compile messages for dynamic enable/disable + */ +#define DEBUG_WARN(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DEBUG_INFO(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DEBUG_TRACE(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else + +/* + * Statically compile messages at different levels + */ +#if (DEBUG_LEVEL < 2) +#define DEBUG_WARN(s, ...) +#else +#define DEBUG_WARN(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if (DEBUG_LEVEL < 3) +#define DEBUG_INFO(s, ...) +#else +#define DEBUG_INFO(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if (DEBUG_LEVEL < 4) +#define DEBUG_TRACE(s, ...) +#else +#define DEBUG_TRACE(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif +#endif + +#ifdef CONFIG_NF_FLOW_COOKIE +typedef int (*flow_cookie_set_func_t)(u32 protocol, __be32 src_ip, __be16 src_port, + __be32 dst_ip, __be16 dst_port, u16 flow_cookie); +/* + * sfe_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb); + +/* + * sfe_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb); + +typedef int (*sfe_ipv6_flow_cookie_set_func_t)(u32 protocol, __be32 src_ip[4], __be16 src_port, + __be32 dst_ip[4], __be16 dst_port, u16 flow_cookie); + +/* + * sfe_ipv6_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); + +/* + * sfe_ipv6_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); + +#endif /*CONFIG_NF_FLOW_COOKIE*/ diff --git a/fast-classifier/src/sfe_backport.h b/fast-classifier/src/sfe_backport.h new file mode 100644 index 000000000..2f8c8ca3c --- /dev/null +++ b/fast-classifier/src/sfe_backport.h @@ -0,0 +1,195 @@ +/* + * sfe_backport.h + * Shortcut forwarding engine compatible header file. + * + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +#include +#else +enum udp_conntrack { + UDP_CT_UNREPLIED, + UDP_CT_REPLIED, + UDP_CT_MAX +}; + +static inline unsigned int * +nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct, + struct nf_conntrack_l4proto *l4proto) +{ +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT + struct nf_conn_timeout *timeout_ext; + unsigned int *timeouts; + + timeout_ext = nf_ct_timeout_find(ct); + if (timeout_ext) + timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); + else + timeouts = l4proto->get_timeouts(net); + + return timeouts; +#else + return l4proto->get_timeouts(net); +#endif /*CONFIG_NF_CONNTRACK_TIMEOUT*/ +} +#endif /*KERNEL_VERSION(3, 7, 0)*/ +#endif /*KERNEL_VERSION(3, 4, 0)*/ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(void *priv, \ + struct sk_buff *SKB, \ + const struct nf_hook_state *state) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(const struct nf_hook_ops *OPS, \ + struct sk_buff *SKB, \ + const struct net_device *UNUSED, \ + const struct net_device *OUT, \ + int (*OKFN)(struct sk_buff *)) +#else +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(unsigned int HOOKNUM, \ + struct sk_buff *SKB, \ + const struct net_device *UNUSED, \ + const struct net_device *OUT, \ + int (*OKFN)(struct sk_buff *)) +#endif + +#define sfe_cm_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__sfe_cm_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define sfe_cm_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__sfe_cm_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define fast_classifier_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__fast_classifier_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define fast_classifier_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__fast_classifier_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .pf = NFPROTO_IPV4, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#else +#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .owner = THIS_MODULE, \ + .pf = NFPROTO_IPV4, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .pf = NFPROTO_IPV6, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#else +#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .owner = THIS_MODULE, \ + .pf = NFPROTO_IPV6, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP6_PRI_NAT_SRC + 1, \ + } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) +#define SFE_NF_CT_DEFAULT_ZONE (&nf_ct_zone_dflt) +#else +#define SFE_NF_CT_DEFAULT_ZONE NF_CT_DEFAULT_ZONE +#endif + +/* + * sfe_dev_get_master + * get master of bridge port, and hold it + */ +static inline struct net_device *sfe_dev_get_master(struct net_device *dev) +{ + struct net_device *master; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) + rcu_read_lock(); + master = netdev_master_upper_dev_get_rcu(dev); + if (master) + dev_hold(master); + + rcu_read_unlock(); +#else + master = dev->master; + if (master) + dev_hold(master); +#endif + return master; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) +#define SFE_DEV_EVENT_PTR(PTR) netdev_notifier_info_to_dev(PTR) +#else +#define SFE_DEV_EVENT_PTR(PTR) (struct net_device *)(PTR) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define SFE_NF_CONN_ACCT(NM) struct nf_conn_acct *NM +#else +#define SFE_NF_CONN_ACCT(NM) struct nf_conn_counter *NM +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define SFE_ACCT_COUNTER(NM) ((NM)->counter) +#else +#define SFE_ACCT_COUNTER(NM) (NM) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +#define sfe_hash_for_each_possible(name, obj, node, member, key) \ + hash_for_each_possible(name, obj, member, key) +#else +#define sfe_hash_for_each_possible(name, obj, node, member, key) \ + hash_for_each_possible(name, obj, node, member, key) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +#define sfe_hash_for_each(name, bkt, node, obj, member) \ + hash_for_each(name, bkt, obj, member) +#else +#define sfe_hash_for_each(name, bkt, node, obj, member) \ + hash_for_each(name, bkt, node, obj, member) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, daddr) +#else +static inline struct neighbour * +sfe_dst_get_neighbour(struct dst_entry *dst, void *daddr) +{ + struct neighbour *neigh = dst_get_neighbour_noref(dst); + + if (neigh) + neigh_hold(neigh); + + return neigh; +} +#endif diff --git a/fast-classifier/src/sfe_cm.h b/fast-classifier/src/sfe_cm.h new file mode 100644 index 000000000..23cbde859 --- /dev/null +++ b/fast-classifier/src/sfe_cm.h @@ -0,0 +1,259 @@ +/* + * sfe_cm.h + * Shortcut forwarding engine. + * + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * connection flags. + */ +#define SFE_CREATE_FLAG_NO_SEQ_CHECK BIT(0) + /* Indicates that we should not check sequence numbers */ +#define SFE_CREATE_FLAG_REMARK_PRIORITY BIT(1) + /* Indicates that we should remark priority of skb */ +#define SFE_CREATE_FLAG_REMARK_DSCP BIT(2) + /* Indicates that we should remark DSCP of packet */ + +/* + * IPv6 address structure + */ +struct sfe_ipv6_addr { + __be32 addr[4]; +}; + +typedef union { + __be32 ip; + struct sfe_ipv6_addr ip6[1]; +} sfe_ip_addr_t; + +/* + * connection creation structure. + */ +struct sfe_connection_create { + int protocol; + struct net_device *src_dev; + struct net_device *dest_dev; + u32 flags; + u32 src_mtu; + u32 dest_mtu; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t src_ip_xlate; + sfe_ip_addr_t dest_ip; + sfe_ip_addr_t dest_ip_xlate; + __be16 src_port; + __be16 src_port_xlate; + __be16 dest_port; + __be16 dest_port_xlate; + u8 src_mac[ETH_ALEN]; + u8 src_mac_xlate[ETH_ALEN]; + u8 dest_mac[ETH_ALEN]; + u8 dest_mac_xlate[ETH_ALEN]; + u8 src_td_window_scale; + u32 src_td_max_window; + u32 src_td_end; + u32 src_td_max_end; + u8 dest_td_window_scale; + u32 dest_td_max_window; + u32 dest_td_end; + u32 dest_td_max_end; + u32 mark; +#ifdef CONFIG_XFRM + u32 original_accel; + u32 reply_accel; +#endif + u32 src_priority; + u32 dest_priority; + u32 src_dscp; + u32 dest_dscp; +}; + +/* + * connection destruction structure. + */ +struct sfe_connection_destroy { + int protocol; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t dest_ip; + __be16 src_port; + __be16 dest_port; +}; + +typedef enum sfe_sync_reason { + SFE_SYNC_REASON_STATS, /* Sync is to synchronize stats */ + SFE_SYNC_REASON_FLUSH, /* Sync is to flush a entry */ + SFE_SYNC_REASON_DESTROY /* Sync is to destroy a entry(requested by connection manager) */ +} sfe_sync_reason_t; + +/* + * Structure used to sync connection stats/state back within the system. + * + * NOTE: The addresses here are NON-NAT addresses, i.e. the true endpoint addressing. + * 'src' is the creator of the connection. + */ +struct sfe_connection_sync { + struct net_device *src_dev; + struct net_device *dest_dev; + int is_v6; /* Is it for ipv6? */ + int protocol; /* IP protocol number (IPPROTO_...) */ + sfe_ip_addr_t src_ip; /* Non-NAT source address, i.e. the creator of the connection */ + sfe_ip_addr_t src_ip_xlate; /* NATed source address */ + __be16 src_port; /* Non-NAT source port */ + __be16 src_port_xlate; /* NATed source port */ + sfe_ip_addr_t dest_ip; /* Non-NAT destination address, i.e. to whom the connection was created */ + sfe_ip_addr_t dest_ip_xlate; /* NATed destination address */ + __be16 dest_port; /* Non-NAT destination port */ + __be16 dest_port_xlate; /* NATed destination port */ + u32 src_td_max_window; + u32 src_td_end; + u32 src_td_max_end; + u64 src_packet_count; + u64 src_byte_count; + u32 src_new_packet_count; + u32 src_new_byte_count; + u32 dest_td_max_window; + u32 dest_td_end; + u32 dest_td_max_end; + u64 dest_packet_count; + u64 dest_byte_count; + u32 dest_new_packet_count; + u32 dest_new_byte_count; + u32 reason; /* reason for stats sync message, i.e. destroy, flush, period sync */ + u64 delta_jiffies; /* Time to be added to the current timeout to keep the connection alive */ +}; + +/* + * connection mark structure + */ +struct sfe_connection_mark { + int protocol; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t dest_ip; + __be16 src_port; + __be16 dest_port; + u32 mark; +}; + +/* + * Expose the hook for the receive processing. + */ +extern int (*athrs_fast_nat_recv)(struct sk_buff *skb); + +/* + * Expose what should be a static flag in the TCP connection tracker. + */ +extern int nf_ct_tcp_no_window_check; + +/* + * This callback will be called in a timer + * at 100 times per second to sync stats back to + * Linux connection track. + * + * A RCU lock is taken to prevent this callback + * from unregistering. + */ +typedef void (*sfe_sync_rule_callback_t)(struct sfe_connection_sync *); + +/* + * IPv4 APIs used by connection manager + */ +int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb); +int sfe_ipv4_create_rule(struct sfe_connection_create *sic); +void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid); +void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev); +void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t callback); +void sfe_ipv4_update_rule(struct sfe_connection_create *sic); +void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark); + +#ifdef SFE_SUPPORT_IPV6 +/* + * IPv6 APIs used by connection manager + */ +int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb); +int sfe_ipv6_create_rule(struct sfe_connection_create *sic); +void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid); +void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev); +void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback); +void sfe_ipv6_update_rule(struct sfe_connection_create *sic); +void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark); +#else +static inline int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) +{ + return 0; +} + +static inline int sfe_ipv6_create_rule(struct sfe_connection_create *sic) +{ + return 0; +} + +static inline void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid) +{ + return; +} + +static inline void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev) +{ + return; +} + +static inline void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback) +{ + return; +} + +static inline void sfe_ipv6_update_rule(struct sfe_connection_create *sic) +{ + return; +} + +static inline void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark) +{ + return; +} +#endif + +/* + * sfe_ipv6_addr_equal() + * compare ipv6 address + * + * return: 1, equal; 0, no equal + */ +static inline int sfe_ipv6_addr_equal(struct sfe_ipv6_addr *a, + struct sfe_ipv6_addr *b) +{ + return a->addr[0] == b->addr[0] && + a->addr[1] == b->addr[1] && + a->addr[2] == b->addr[2] && + a->addr[3] == b->addr[3]; +} + +/* + * sfe_ipv4_addr_equal() + * compare ipv4 address + * + * return: 1, equal; 0, no equal + */ +#define sfe_ipv4_addr_equal(a, b) ((u32)(a) == (u32)(b)) + +/* + * sfe_addr_equal() + * compare ipv4 or ipv6 address + * + * return: 1, equal; 0, no equal + */ +static inline int sfe_addr_equal(sfe_ip_addr_t *a, + sfe_ip_addr_t *b, int is_v4) +{ + return is_v4 ? sfe_ipv4_addr_equal(a->ip, b->ip) : sfe_ipv6_addr_equal(a->ip6, b->ip6); +} diff --git a/fast-classifier/src/userspace_example.c b/fast-classifier/src/userspace_example.c new file mode 100644 index 000000000..4f4113d99 --- /dev/null +++ b/fast-classifier/src/userspace_example.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2013,2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include + +static struct nl_sock *sock; +static struct nl_sock *sock_event; +static int family; +static int grp_id; + +static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = { + [FAST_CLASSIFIER_A_TUPLE] = { .type = NLA_UNSPEC }, +}; + +void dump_fc_tuple(struct fast_classifier_tuple *fc_msg) +{ + char src_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; + + printf("TUPLE: %d, %s, %s, %d, %d" + " SMAC=%02x:%02x:%02x:%02x:%02x:%02x", + " DMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + fc_msg->proto, + inet_ntop(AF_INET, + &fc_msg->src_saddr.in.s_addr, + src_str, + INET_ADDRSTRLEN), + inet_ntop(AF_INET, + &fc_msg->dst_saddr.in.s_addr, + dst_str, + INET_ADDRSTRLEN), + fc_msg->sport, fc_msg->dport, + fc_msg->smac[0], fc_msg->smac[1], fc_msg->smac[2], + fc_msg->smac[3], fc_msg->smac[4], fc_msg->smac[5], + fc_msg->dmac[0], fc_msg->dmac[1], fc_msg->dmac[2], + fc_msg->dmac[3], fc_msg->dmac[4], fc_msg->dmac[5]); +} + +static int parse_cb(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *gnlh = nlmsg_data(nlh); + struct nlattr *attrs[FAST_CLASSIFIER_A_MAX]; + + genlmsg_parse(nlh, 0, attrs, FAST_CLASSIFIER_A_MAX, fast_classifier_genl_policy); + + switch (gnlh->cmd) { + case FAST_CLASSIFIER_C_OFFLOADED: + printf("Got a offloaded message\n"); + dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE])); + return NL_OK; + case FAST_CLASSIFIER_C_DONE: + printf("Got a done message\n"); + dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE])); + return NL_OK; + } + + return NL_SKIP; +} + +int fast_classifier_init(void) +{ + int err; + + sock = nl_socket_alloc(); + if (!sock) { + printf("Unable to allocation socket.\n"); + return -1; + } + genl_connect(sock); + + sock_event = nl_socket_alloc(); + if (!sock_event) { + nl_close(sock); + nl_socket_free(sock); + printf("Unable to allocation socket.\n"); + return -1; + } + genl_connect(sock_event); + + family = genl_ctrl_resolve(sock, FAST_CLASSIFIER_GENL_NAME); + if (family < 0) { + nl_close(sock_event); + nl_close(sock); + nl_socket_free(sock); + nl_socket_free(sock_event); + printf("Unable to resolve family\n"); + return -1; + } + + grp_id = genl_ctrl_resolve_grp(sock, FAST_CLASSIFIER_GENL_NAME, + FAST_CLASSIFIER_GENL_MCGRP); + if (grp_id < 0) { + printf("Unable to resolve mcast group\n"); + return -1; + } + + err = nl_socket_add_membership(sock_event, grp_id); + if (err < 0) { + printf("Unable to add membership\n"); + return -1; + } + + nl_socket_disable_seq_check(sock_event); + nl_socket_modify_cb(sock_event, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL); + + return 0; +} + +void fast_classifier_close(void) +{ + nl_close(sock_event); + nl_close(sock); + nl_socket_free(sock_event); + nl_socket_free(sock); +} + +void fast_classifier_ipv4_offload(unsigned char proto, unsigned long src_saddr, + unsigned long dst_saddr, unsigned short sport, + unsigned short dport) +{ + struct nl_msg *msg; + int ret; +#ifdef DEBUG + char src_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; +#endif + struct fast_classifier_tuple fc_msg; + +#ifdef DEBUG + printf("DEBUG: would offload: %d, %s, %s, %d, %d\n", proto, + inet_ntop(AF_INET, &src_saddr, src_str, INET_ADDRSTRLEN), + inet_ntop(AF_INET, &dst_saddr, dst_str, INET_ADDRSTRLEN), + sport, dport); +#endif + + fc_msg.proto = proto; + fc_msg.src_saddr.in.s_addr = src_saddr; + fc_msg.dst_saddr.in.s_addr = dst_saddr; + fc_msg.sport = sport; + fc_msg.dport = dport; + fc_msg.smac[0] = 'a'; + fc_msg.smac[1] = 'b'; + fc_msg.smac[2] = 'c'; + fc_msg.smac[3] = 'd'; + fc_msg.smac[4] = 'e'; + fc_msg.smac[5] = 'f'; + fc_msg.dmac[0] = 'f'; + fc_msg.dmac[1] = 'e'; + fc_msg.dmac[2] = 'd'; + fc_msg.dmac[3] = 'c'; + fc_msg.dmac[4] = 'b'; + fc_msg.dmac[5] = 'a'; + + if (fast_classifier_init() < 0) { + printf("Unable to init generic netlink\n"); + exit(1); + } + + msg = nlmsg_alloc(); + if (!msg) { + nl_socket_free(sock); + printf("Unable to allocate message\n"); + return; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, + FAST_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST, + FAST_CLASSIFIER_C_OFFLOAD, FAST_CLASSIFIER_GENL_VERSION); + nla_put(msg, 1, sizeof(fc_msg), &fc_msg); + + ret = nl_send_auto_complete(sock, msg); + + nlmsg_free(msg); + if (ret < 0) { + printf("nlmsg_free failed"); + nl_close(sock); + nl_socket_free(sock); + return; + } + + ret = nl_wait_for_ack(sock); + if (ret < 0) { + printf("wait for ack failed"); + nl_close(sock); + nl_socket_free(sock); + return; + } +} + +void fast_classifier_listen_for_messages(void) +{ + printf("waiting for netlink events\n"); + + while (1) { + nl_recvmsgs_default(sock_event); + } +} + +int main(int argc, char *argv[]) +{ + if (fast_classifier_init() < 0) { + printf("Unable to init generic netlink\n"); + exit(1); + } + + fast_classifier_ipv4_offload('a', 0, 0, 0, 0); + + /* this never returns */ + fast_classifier_listen_for_messages(); + + fast_classifier_close(); + + return 0; +} diff --git a/libmbim/Makefile b/libmbim/Makefile new file mode 100644 index 000000000..b9563219e --- /dev/null +++ b/libmbim/Makefile @@ -0,0 +1,97 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libmbim.git +PKG_SOURCE_VERSION:=c90c7c5b877de6e413b4833aaf1a42d2d128b051 + +PKG_NAME:=libmbim +PKG_VERSION:=1.25.3-$(PKG_SOURCE_VERSION) +PKG_RELEASE:=10 + +PKG_MAINTAINER:=Nicholas Smith + +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +CONFIGURE_ARGS += \ + --disable-static \ + --disable-gtk-doc \ + --disable-gtk-doc-html \ + --disable-gtk-doc-pdf \ + --disable-silent-rules \ + --enable-more-warnings=yes + +define Package/libmbim + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:=+glib2 + TITLE:=Helper library and utils to talk to MBIM enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libmbim + LICENSE:=LGPL-2.0-or-later + LICENSE_FILES:=COPYING.LIB +endef + +define Package/libmbim/description + Helper library to talk to MBIM enabled modems. + Add mbim-utils for extra utilities. +endef + +define Package/mbim-utils + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libmbim + TITLE:=Utilities to talk to MBIM enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libmbim + LICENSE:=GPL-2.0-or-later + LICENSE_FILES:=COPYING +endef + +CONFIGURE_ARGS += \ + --without-udev \ + --without-udev-base-dir + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) \ + $(PKG_INSTALL_DIR)/usr/include/libmbim-glib \ + $(1)/usr/include/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so* \ + $(1)/usr/lib/ + + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mbim-glib.pc \ + $(1)/usr/lib/pkgconfig +endef + +define Package/libmbim/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libmbim*.so.* \ + $(1)/usr/lib/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/mbim-proxy $(1)/usr/lib/ +endef + +define Package/mbim-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbimcli $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mbim-network $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,libmbim)) +$(eval $(call BuildPackage,mbim-utils)) diff --git a/libqmi/Config.in b/libqmi/Config.in new file mode 100644 index 000000000..6f35b7453 --- /dev/null +++ b/libqmi/Config.in @@ -0,0 +1,16 @@ +menu "Configuration" + depends on PACKAGE_libqmi + +config LIBQMI_WITH_MBIM_QMUX + bool "Include MBIM QMUX service support" + default y + help + Compile libqmi with QMI-over-MBIM support + +config LIBQMI_WITH_QRTR_GLIB + bool "Include QRTR support" + default y + help + Compile libqmi with QRTR support + +endmenu diff --git a/libqmi/Makefile b/libqmi/Makefile new file mode 100644 index 000000000..a10ea0121 --- /dev/null +++ b/libqmi/Makefile @@ -0,0 +1,110 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/libqmi.git +PKG_SOURCE_VERSION:=29fab8a1d4496ca5a1d32bb486013b1868a718ba +PKG_NAME:=libqmi +PKG_VERSION:=1.29.3-$(PKG_SOURCE_VERSION) +PKG_RELEASE:=10 + +PKG_FIXUP:=autoreconf +PKG_MAINTAINER:=Nicholas Smith + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/libqmi/config + source "$(SOURCE)/Config.in" +endef + +define Package/libqmi + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:= \ + +glib2 \ + +LIBQMI_WITH_MBIM_QMUX:libmbim \ + +LIBQMI_WITH_QRTR_GLIB:libqrtr-glib + TITLE:=Helper library to talk to QMI enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libqmi + LICENSE:=LGPL-2.0-or-later + LICENSE_FILES:=COPYING.LIB +endef + +define Package/libqmi/description + Helper library talk to QMI enabled modems. + Add qmi-utils for extra utilities. +endef + +define Package/qmi-utils + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libqmi + TITLE:=Utilities to talk to QMI enabled modems + URL:=https://www.freedesktop.org/wiki/Software/libqmi + LICENSE:=GPL-2.0-or-later + LICENSE_FILES:=COPYING +endef + +define Package/libqmi-utils/description + Utils to talk to QMI enabled modems +endef + +CONFIGURE_ARGS += \ + --disable-static \ + --disable-gtk-doc \ + --disable-gtk-doc-html \ + --disable-gtk-doc-pdf \ + --disable-silent-rules \ + --enable-firmware-update \ + --$(if $(LIBQMI_WITH_MBIM_QMUX),en,dis)able-mbim-qmux \ + --$(if $(LIBQMI_WITH_QRTR_GLIB),en,dis)able-qrtr \ + --enable-more-warnings=yes \ + --without-udev \ + --without-udev-base-dir + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) \ + $(PKG_INSTALL_DIR)/usr/include/libqmi-glib \ + $(1)/usr/include/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so* \ + $(1)/usr/lib/ + + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/qmi-glib.pc \ + $(1)/usr/lib/pkgconfig +endef + +define Package/libqmi/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libqmi*.so.* \ + $(1)/usr/lib/ + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/qmi-proxy $(1)/usr/lib/ +endef + +define Package/qmi-utils/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmicli $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-network $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/qmi-firmware-update $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,libqmi)) +$(eval $(call BuildPackage,qmi-utils)) diff --git a/luci-app-dsvpn/po/fr/dsvpn.po b/luci-app-dsvpn/po/fr/dsvpn.po index 3bf5077a1..448d90c08 100755 --- a/luci-app-dsvpn/po/fr/dsvpn.po +++ b/luci-app-dsvpn/po/fr/dsvpn.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -10,7 +10,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.5.2\n" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:35 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:38 msgid "Client" msgstr "Client" @@ -21,13 +21,13 @@ msgstr "DSVPN" #: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:31 msgid "Enabled" -msgstr "Activé" +msgstr "Activer" #: luci-app-dsvpn/root/usr/share/rpcd/acl.d/luci-app-dsvpn.json:3 msgid "Grant access to DSVPN" msgstr "Accorder l'accès à DSVPN" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 msgid "Host" msgstr "Hôte" @@ -35,34 +35,34 @@ msgstr "Hôte" msgid "Instances" msgstr "Instances" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:49 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:52 msgid "Interface name" msgstr "Nom de l'interface" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:48 msgid "Key" msgstr "Clef" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:61 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 msgid "Label" msgstr "Étiquette" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:53 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:56 msgid "Local IP" msgstr "Adresse IP locale" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:37 msgid "Mode" msgstr "Mode" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 msgid "Port" msgstr "Port" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:57 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:60 msgid "Remote IP" msgstr "IP Distante" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:36 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 msgid "Server" msgstr "Serveur" diff --git a/luci-app-dsvpn/po/fr/dsvpn.po~ b/luci-app-dsvpn/po/fr/dsvpn.po~ new file mode 100644 index 000000000..dc421eb01 --- /dev/null +++ b/luci-app-dsvpn/po/fr/dsvpn.po~ @@ -0,0 +1,68 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:35 +msgid "Client" +msgstr "Client" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:24 +#: luci-app-dsvpn/root/usr/share/luci/menu.d/luci-app-dsvpn.json:3 +msgid "DSVPN" +msgstr "DSVPN" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:31 +msgid "Enabled" +msgstr "Activer" + +#: luci-app-dsvpn/root/usr/share/rpcd/acl.d/luci-app-dsvpn.json:3 +msgid "Grant access to DSVPN" +msgstr "Accorder l'accès à DSVPN" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 +msgid "Host" +msgstr "Hôte" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:26 +msgid "Instances" +msgstr "Instances" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:49 +msgid "Interface name" +msgstr "Nom de l'interface" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 +msgid "Key" +msgstr "Clef" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:61 +msgid "Label" +msgstr "Étiquette" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:53 +msgid "Local IP" +msgstr "Adresse IP locale" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 +msgid "Mode" +msgstr "Mode" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 +msgid "Port" +msgstr "Port" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:57 +msgid "Remote IP" +msgstr "IP Distante" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:36 +msgid "Server" +msgstr "Serveur" diff --git a/luci-app-dsvpn/po/ru/dsvpn.po b/luci-app-dsvpn/po/ru/dsvpn.po new file mode 100644 index 000000000..a926fd1ab --- /dev/null +++ b/luci-app-dsvpn/po/ru/dsvpn.po @@ -0,0 +1,69 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:38 +msgid "Client" +msgstr "Клиент" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:24 +#: luci-app-dsvpn/root/usr/share/luci/menu.d/luci-app-dsvpn.json:3 +msgid "DSVPN" +msgstr "DSVPN" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:31 +msgid "Enabled" +msgstr "Установлено" + +#: luci-app-dsvpn/root/usr/share/rpcd/acl.d/luci-app-dsvpn.json:3 +msgid "Grant access to DSVPN" +msgstr "Полный доступ к DSVPN" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 +msgid "Host" +msgstr "Хост" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:26 +msgid "Instances" +msgstr "Экземпляры" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:52 +msgid "Interface name" +msgstr "Имя интерфейса" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:48 +msgid "Key" +msgstr "Ключ" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 +msgid "Label" +msgstr "Метка" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:56 +msgid "Local IP" +msgstr "Локальный IP" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:37 +msgid "Mode" +msgstr "Режим" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 +msgid "Port" +msgstr "Порт" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:60 +msgid "Remote IP" +msgstr "Удаленный IP" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 +msgid "Server" +msgstr "Сервер" diff --git a/luci-app-dsvpn/po/templates/dsvpn.pot b/luci-app-dsvpn/po/templates/dsvpn.pot index 8f77636dc..4b5645646 100755 --- a/luci-app-dsvpn/po/templates/dsvpn.pot +++ b/luci-app-dsvpn/po/templates/dsvpn.pot @@ -1,7 +1,7 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:35 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:38 msgid "Client" msgstr "" @@ -18,7 +18,7 @@ msgstr "" msgid "Grant access to DSVPN" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 msgid "Host" msgstr "" @@ -26,34 +26,34 @@ msgstr "" msgid "Instances" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:49 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:52 msgid "Interface name" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:48 msgid "Key" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:61 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 msgid "Label" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:53 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:56 msgid "Local IP" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:37 msgid "Mode" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 msgid "Port" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:57 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:60 msgid "Remote IP" msgstr "" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:36 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 msgid "Server" msgstr "" diff --git a/luci-app-dsvpn/po/zh_Hans/dsvpn.po b/luci-app-dsvpn/po/zh_Hans/dsvpn.po index 177492257..e0379098d 100755 --- a/luci-app-dsvpn/po/zh_Hans/dsvpn.po +++ b/luci-app-dsvpn/po/zh_Hans/dsvpn.po @@ -1,16 +1,16 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-12-04 16:03+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-05 11:40+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:35 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:38 msgid "Client" msgstr "客户端" @@ -21,13 +21,13 @@ msgstr "DSVPN" #: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:31 msgid "Enabled" -msgstr "开启" +msgstr "启用" #: luci-app-dsvpn/root/usr/share/rpcd/acl.d/luci-app-dsvpn.json:3 msgid "Grant access to DSVPN" msgstr "授予对DSVPN的访问权限" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 msgid "Host" msgstr "主机" @@ -35,34 +35,34 @@ msgstr "主机" msgid "Instances" msgstr "实例" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:49 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:52 msgid "Interface name" msgstr "接口名称" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:48 msgid "Key" msgstr "秘钥" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:61 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 msgid "Label" msgstr "标签" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:53 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:56 msgid "Local IP" msgstr "本地IP" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:37 msgid "Mode" msgstr "模式" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 msgid "Port" msgstr "端口" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:57 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:60 msgid "Remote IP" msgstr "远程IP" -#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:36 +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 msgid "Server" msgstr "服务器" diff --git a/luci-app-dsvpn/po/zh_Hans/dsvpn.po~ b/luci-app-dsvpn/po/zh_Hans/dsvpn.po~ new file mode 100644 index 000000000..177492257 --- /dev/null +++ b/luci-app-dsvpn/po/zh_Hans/dsvpn.po~ @@ -0,0 +1,68 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-04 16:03+0000\n" +"Last-Translator: antrouter \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:35 +msgid "Client" +msgstr "客户端" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:24 +#: luci-app-dsvpn/root/usr/share/luci/menu.d/luci-app-dsvpn.json:3 +msgid "DSVPN" +msgstr "DSVPN" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:31 +msgid "Enabled" +msgstr "开启" + +#: luci-app-dsvpn/root/usr/share/rpcd/acl.d/luci-app-dsvpn.json:3 +msgid "Grant access to DSVPN" +msgstr "授予对DSVPN的访问权限" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:39 +msgid "Host" +msgstr "主机" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:26 +msgid "Instances" +msgstr "实例" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:49 +msgid "Interface name" +msgstr "接口名称" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:45 +msgid "Key" +msgstr "秘钥" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:61 +msgid "Label" +msgstr "标签" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:53 +msgid "Local IP" +msgstr "本地IP" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:34 +msgid "Mode" +msgstr "模式" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:42 +msgid "Port" +msgstr "端口" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:57 +msgid "Remote IP" +msgstr "远程IP" + +#: luci-app-dsvpn/htdocs/luci-static/resources/view/services/dsvpn.js:36 +msgid "Server" +msgstr "服务器" diff --git a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js index 6c0c7ae73..b30d57c76 100755 --- a/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js +++ b/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js @@ -282,7 +282,7 @@ return view.extend({ fwtool.addLimitBurstOption(s); o = s.taboption('advanced', form.Flag, 'v2ray', _('Use V2Ray'), - _('Forwards ports from server using V2Ray proxy (if enabled) instead of VPN')); + _('Forward a port (not a range) from server using V2Ray proxy (if enabled) instead of VPN')); o.modalonly = true; o.editable = true; o.depends({ src: 'vpn', '!contains': true }); diff --git a/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po index 7a637e9c1..8fac07bca 100755 --- a/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po +++ b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -14,15 +14,15 @@ msgstr "" msgid "Advanced Settings" msgstr "Configuration avancée" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:38 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:41 msgid "Client" msgstr "Client" #: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:34 msgid "Enabled" -msgstr "Activé" +msgstr "Activer" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 msgid "Force fallback cipher" msgstr "Forcer le chiffrement de secours" @@ -39,7 +39,7 @@ msgstr "Glorytun TCP" msgid "Grant access to glorytun TCP" msgstr "Accorder l'accès à Glorytun TCP" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 msgid "Host" msgstr "Hôte" @@ -47,50 +47,50 @@ msgstr "Hôte" msgid "Instances" msgstr "Instances" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:52 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:55 msgid "Interface name" msgstr "Nom de l'interface" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:51 msgid "Key" msgstr "Clef" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:82 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 msgid "Label" msgstr "Étiquette" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:56 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:59 msgid "Local IP" msgstr "Adresse IP locale" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:64 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:67 msgid "MPTCP" msgstr "MPTCP" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:40 msgid "Mode" msgstr "Mode" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:77 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:78 msgid "Multiqueue" msgstr "Multiqueue" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 msgid "Port" msgstr "Port" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:60 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:63 msgid "Remote IP" msgstr "IP Distante" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:39 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 msgid "Server" msgstr "Serveur" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:72 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:73 msgid "Timeout" msgstr "Temporisation" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 msgid "chacha" msgstr "Chacha" diff --git a/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po~ b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po~ new file mode 100644 index 000000000..b8618b9f4 --- /dev/null +++ b/luci-app-glorytun-tcp/po/fr/glorytun-tcp.po~ @@ -0,0 +1,96 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:32 +msgid "Advanced Settings" +msgstr "Configuration avancée" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:38 +msgid "Client" +msgstr "Client" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:34 +msgid "Enabled" +msgstr "Activer" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +msgid "Force fallback cipher" +msgstr "Forcer le chiffrement de secours" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:31 +msgid "General Settings" +msgstr "Paramètres généraux" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:24 +#: luci-app-glorytun-tcp/root/usr/share/luci/menu.d/luci-app-glorytun-tcp.json:3 +msgid "Glorytun TCP" +msgstr "Glorytun TCP" + +#: luci-app-glorytun-tcp/root/usr/share/rpcd/acl.d/luci-app-glorytun-tcp.json:3 +msgid "Grant access to glorytun TCP" +msgstr "Accorder l'accès à Glorytun TCP" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 +msgid "Host" +msgstr "Hôte" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:26 +msgid "Instances" +msgstr "Instances" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:52 +msgid "Interface name" +msgstr "Nom de l'interface" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 +msgid "Key" +msgstr "Clef" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:82 +msgid "Label" +msgstr "Étiquette" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:56 +msgid "Local IP" +msgstr "Adresse IP locale" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:64 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 +msgid "Mode" +msgstr "Mode" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:77 +msgid "Multiqueue" +msgstr "Multiqueue" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 +msgid "Port" +msgstr "Port" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:60 +msgid "Remote IP" +msgstr "IP Distante" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:39 +msgid "Server" +msgstr "Serveur" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:72 +msgid "Timeout" +msgstr "Temporisation" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +msgid "chacha" +msgstr "Chacha" diff --git a/luci-app-glorytun-tcp/po/ru/glorytun-tcp.po b/luci-app-glorytun-tcp/po/ru/glorytun-tcp.po new file mode 100644 index 000000000..5996b38c4 --- /dev/null +++ b/luci-app-glorytun-tcp/po/ru/glorytun-tcp.po @@ -0,0 +1,97 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:32 +msgid "Advanced Settings" +msgstr "Дополнительные настройки" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:41 +msgid "Client" +msgstr "Клиент" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:34 +msgid "Enabled" +msgstr "Установлено" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 +msgid "Force fallback cipher" +msgstr "Принудительное резервное шифрование" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:31 +msgid "General Settings" +msgstr "Основные настройки" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:24 +#: luci-app-glorytun-tcp/root/usr/share/luci/menu.d/luci-app-glorytun-tcp.json:3 +msgid "Glorytun TCP" +msgstr "Glorytun TCP" + +#: luci-app-glorytun-tcp/root/usr/share/rpcd/acl.d/luci-app-glorytun-tcp.json:3 +msgid "Grant access to glorytun TCP" +msgstr "Полный доступ к glorytun TCP" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 +msgid "Host" +msgstr "Хост" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:26 +msgid "Instances" +msgstr "Экземпляры" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:55 +msgid "Interface name" +msgstr "Имя интерфейса" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:51 +msgid "Key" +msgstr "Ключ" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 +msgid "Label" +msgstr "Метка" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:59 +msgid "Local IP" +msgstr "Локальный IP" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:67 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:40 +msgid "Mode" +msgstr "Режим" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:78 +msgid "Multiqueue" +msgstr "Мультиочередь" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 +msgid "Port" +msgstr "Порт" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:63 +msgid "Remote IP" +msgstr "Удаленный IP" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 +msgid "Server" +msgstr "Сервер" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:73 +msgid "Timeout" +msgstr "Таймаут" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 +msgid "chacha" +msgstr "Chacha" diff --git a/luci-app-glorytun-tcp/po/templates/glorytun-tcp.pot b/luci-app-glorytun-tcp/po/templates/glorytun-tcp.pot index 4f7759dc3..9cd0f6d60 100755 --- a/luci-app-glorytun-tcp/po/templates/glorytun-tcp.pot +++ b/luci-app-glorytun-tcp/po/templates/glorytun-tcp.pot @@ -5,7 +5,7 @@ msgstr "Content-Type: text/plain; charset=UTF-8" msgid "Advanced Settings" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:38 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:41 msgid "Client" msgstr "" @@ -13,7 +13,7 @@ msgstr "" msgid "Enabled" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 msgid "Force fallback cipher" msgstr "" @@ -30,7 +30,7 @@ msgstr "" msgid "Grant access to glorytun TCP" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 msgid "Host" msgstr "" @@ -38,50 +38,50 @@ msgstr "" msgid "Instances" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:52 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:55 msgid "Interface name" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:51 msgid "Key" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:82 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 msgid "Label" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:56 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:59 msgid "Local IP" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:64 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:67 msgid "MPTCP" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:40 msgid "Mode" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:77 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:78 msgid "Multiqueue" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 msgid "Port" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:60 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:63 msgid "Remote IP" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:39 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 msgid "Server" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:72 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:73 msgid "Timeout" msgstr "" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 msgid "chacha" msgstr "" diff --git a/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po b/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po index debdafdef..522561c56 100755 --- a/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po +++ b/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po @@ -1,28 +1,28 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-12-04 16:03+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-05 11:40+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:32 msgid "Advanced Settings" msgstr "高级设置" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:38 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:41 msgid "Client" msgstr "客户端" #: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:34 msgid "Enabled" -msgstr "开启" +msgstr "启用" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 msgid "Force fallback cipher" msgstr "强制回退密码" @@ -39,7 +39,7 @@ msgstr "glorytun TCP" msgid "Grant access to glorytun TCP" msgstr "授予访问glorytun TCP的权限" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 msgid "Host" msgstr "主机" @@ -47,50 +47,50 @@ msgstr "主机" msgid "Instances" msgstr "实例" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:52 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:55 msgid "Interface name" msgstr "接口名称" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:51 msgid "Key" msgstr "秘钥" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:82 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 msgid "Label" msgstr "标签" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:56 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:59 msgid "Local IP" msgstr "本地IP" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:64 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:67 msgid "MPTCP" -msgstr "聚合" +msgstr "MPTCP" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:40 msgid "Mode" msgstr "模式" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:77 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:78 msgid "Multiqueue" msgstr "多队列" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 msgid "Port" msgstr "端口" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:60 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:63 msgid "Remote IP" msgstr "远程IP" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:39 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 msgid "Server" msgstr "服务器" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:72 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:73 msgid "Timeout" msgstr "超时" -#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:70 msgid "chacha" msgstr "chacha密码" diff --git a/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po~ b/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po~ new file mode 100644 index 000000000..1db94cdb9 --- /dev/null +++ b/luci-app-glorytun-tcp/po/zh_Hans/glorytun-tcp.po~ @@ -0,0 +1,96 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:21+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:32 +msgid "Advanced Settings" +msgstr "高级设置" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:38 +msgid "Client" +msgstr "客户端" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:34 +msgid "Enabled" +msgstr "开启" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +msgid "Force fallback cipher" +msgstr "强制回退密码" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:31 +msgid "General Settings" +msgstr "通用设置" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:24 +#: luci-app-glorytun-tcp/root/usr/share/luci/menu.d/luci-app-glorytun-tcp.json:3 +msgid "Glorytun TCP" +msgstr "glorytun TCP" + +#: luci-app-glorytun-tcp/root/usr/share/rpcd/acl.d/luci-app-glorytun-tcp.json:3 +msgid "Grant access to glorytun TCP" +msgstr "授予访问glorytun TCP的权限" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:42 +msgid "Host" +msgstr "主机" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:26 +msgid "Instances" +msgstr "实例" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:52 +msgid "Interface name" +msgstr "接口名称" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:48 +msgid "Key" +msgstr "秘钥" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:82 +msgid "Label" +msgstr "标签" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:56 +msgid "Local IP" +msgstr "本地IP" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:64 +msgid "MPTCP" +msgstr "聚合" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:37 +msgid "Mode" +msgstr "模式" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:77 +msgid "Multiqueue" +msgstr "多队列" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:45 +msgid "Port" +msgstr "端口" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:60 +msgid "Remote IP" +msgstr "远程IP" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:39 +msgid "Server" +msgstr "服务器" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:72 +msgid "Timeout" +msgstr "超时" + +#: luci-app-glorytun-tcp/htdocs/luci-static/resources/view/services/glorytun-tcp.js:68 +msgid "chacha" +msgstr "chacha密码" diff --git a/luci-app-glorytun-udp/po/fr/glorytun-udp.po b/luci-app-glorytun-udp/po/fr/glorytun-udp.po index deedf9815..cab674d18 100755 --- a/luci-app-glorytun-udp/po/fr/glorytun-udp.po +++ b/luci-app-glorytun-udp/po/fr/glorytun-udp.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -14,23 +14,23 @@ msgstr "" msgid "Advanced Settings" msgstr "Configuration avancée" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:46 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:49 msgid "Client" msgstr "Client" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:85 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:86 msgid "Clock sync tolerance" msgstr "Tolérance de synchronisation d'horloge" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:95 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:96 msgid "Dynamic rate detection" msgstr "Détection dynamique de la vitesse" #: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:42 msgid "Enabled" -msgstr "Activé" +msgstr "Activer" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:78 msgid "Force fallback cipher" msgstr "Forcer le chiffrement de secours" @@ -47,7 +47,7 @@ msgstr "Glorytun UDP" msgid "Grant access to glorytun UDP" msgstr "Accorder l'accès à Glorytun UDP" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 msgid "Host" msgstr "Hôte" @@ -55,54 +55,54 @@ msgstr "Hôte" msgid "Instances" msgstr "Instances" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:60 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:63 msgid "Interface name" msgstr "Nom de l'interface" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:90 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:91 msgid "Keep alive timeout" msgstr "Délai de maintien de la connexion (Keep Alive)" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:75 msgid "Keep the tunnel device after exiting" msgstr "Gardez le périphérique tunnel après avoir quitté" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:59 msgid "Key" msgstr "Clef" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:80 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:81 msgid "Key rotation timeout" msgstr "Délai de rotation des clés" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:99 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 msgid "Label" msgstr "Étiquette" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:64 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:67 msgid "Local IP" msgstr "Adresse IP locale" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:48 msgid "Mode" msgstr "Mode" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:75 msgid "Persist" msgstr "Persister" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 msgid "Port" msgstr "Port" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:68 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:71 msgid "Remote IP" msgstr "IP Distante" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:47 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 msgid "Server" msgstr "Serveur" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:78 msgid "chacha" msgstr "Chacha" diff --git a/luci-app-glorytun-udp/po/fr/glorytun-udp.po~ b/luci-app-glorytun-udp/po/fr/glorytun-udp.po~ new file mode 100644 index 000000000..6c7e564dc --- /dev/null +++ b/luci-app-glorytun-udp/po/fr/glorytun-udp.po~ @@ -0,0 +1,108 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:40 +msgid "Advanced Settings" +msgstr "Configuration avancée" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:46 +msgid "Client" +msgstr "Client" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:85 +msgid "Clock sync tolerance" +msgstr "Tolérance de synchronisation d'horloge" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:95 +msgid "Dynamic rate detection" +msgstr "Détection dynamique de la vitesse" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:42 +msgid "Enabled" +msgstr "Activer" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +msgid "Force fallback cipher" +msgstr "Forcer le chiffrement de secours" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:39 +msgid "General Settings" +msgstr "Paramètres généraux" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:32 +#: luci-app-glorytun-udp/root/usr/share/luci/menu.d/luci-app-glorytun-udp.json:3 +msgid "Glorytun UDP" +msgstr "Glorytun UDP" + +#: luci-app-glorytun-udp/root/usr/share/rpcd/acl.d/luci-app-glorytun-udp.json:3 +msgid "Grant access to glorytun UDP" +msgstr "Accorder l'accès à Glorytun UDP" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 +msgid "Host" +msgstr "Hôte" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:34 +msgid "Instances" +msgstr "Instances" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:60 +msgid "Interface name" +msgstr "Nom de l'interface" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:90 +msgid "Keep alive timeout" +msgstr "Délai de maintien de la connexion (Keep Alive)" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +msgid "Keep the tunnel device after exiting" +msgstr "Gardez le périphérique tunnel après avoir quitté" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 +msgid "Key" +msgstr "Clef" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:80 +msgid "Key rotation timeout" +msgstr "Délai de rotation des clés" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:99 +msgid "Label" +msgstr "Étiquette" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:64 +msgid "Local IP" +msgstr "Adresse IP locale" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 +msgid "Mode" +msgstr "Mode" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +msgid "Persist" +msgstr "Persister" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 +msgid "Port" +msgstr "Port" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:68 +msgid "Remote IP" +msgstr "IP Distante" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:47 +msgid "Server" +msgstr "Serveur" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +msgid "chacha" +msgstr "Chacha" diff --git a/luci-app-glorytun-udp/po/ru/glorytun-udp.po b/luci-app-glorytun-udp/po/ru/glorytun-udp.po new file mode 100644 index 000000000..29e624040 --- /dev/null +++ b/luci-app-glorytun-udp/po/ru/glorytun-udp.po @@ -0,0 +1,109 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:40 +msgid "Advanced Settings" +msgstr "Дополнительные настройки" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:49 +msgid "Client" +msgstr "Клиент" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:86 +msgid "Clock sync tolerance" +msgstr "Допуск синхронизации часов" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:96 +msgid "Dynamic rate detection" +msgstr "Определение динамической скорости" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:42 +msgid "Enabled" +msgstr "Установлено" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:78 +msgid "Force fallback cipher" +msgstr "Принудительное резервное шифрование" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:39 +msgid "General Settings" +msgstr "Основные настройки" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:32 +#: luci-app-glorytun-udp/root/usr/share/luci/menu.d/luci-app-glorytun-udp.json:3 +msgid "Glorytun UDP" +msgstr "Glorytun UDP" + +#: luci-app-glorytun-udp/root/usr/share/rpcd/acl.d/luci-app-glorytun-udp.json:3 +msgid "Grant access to glorytun UDP" +msgstr "Полный доступ к glorytun UDP" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 +msgid "Host" +msgstr "Хост" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:34 +msgid "Instances" +msgstr "Экземпляры" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:63 +msgid "Interface name" +msgstr "Имя интерфейса" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:91 +msgid "Keep alive timeout" +msgstr "Таймаут активности" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:75 +msgid "Keep the tunnel device after exiting" +msgstr "Сохранить туннель после выхода" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:59 +msgid "Key" +msgstr "Ключ" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:81 +msgid "Key rotation timeout" +msgstr "Тайм-аут смены ключа" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 +msgid "Label" +msgstr "Метка" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:67 +msgid "Local IP" +msgstr "Локальный IP" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:48 +msgid "Mode" +msgstr "Режим" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:75 +msgid "Persist" +msgstr "Удерживать" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 +msgid "Port" +msgstr "Порт" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:71 +msgid "Remote IP" +msgstr "Удаленный IP" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 +msgid "Server" +msgstr "Сервер" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:78 +msgid "chacha" +msgstr "Chacha" diff --git a/luci-app-glorytun-udp/po/templates/glorytun-udp.pot b/luci-app-glorytun-udp/po/templates/glorytun-udp.pot index 04edec275..c292fcace 100755 --- a/luci-app-glorytun-udp/po/templates/glorytun-udp.pot +++ b/luci-app-glorytun-udp/po/templates/glorytun-udp.pot @@ -5,15 +5,15 @@ msgstr "Content-Type: text/plain; charset=UTF-8" msgid "Advanced Settings" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:46 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:49 msgid "Client" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:85 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:86 msgid "Clock sync tolerance" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:95 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:96 msgid "Dynamic rate detection" msgstr "" @@ -21,7 +21,7 @@ msgstr "" msgid "Enabled" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:78 msgid "Force fallback cipher" msgstr "" @@ -38,7 +38,7 @@ msgstr "" msgid "Grant access to glorytun UDP" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 msgid "Host" msgstr "" @@ -46,54 +46,54 @@ msgstr "" msgid "Instances" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:60 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:63 msgid "Interface name" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:90 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:91 msgid "Keep alive timeout" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:75 msgid "Keep the tunnel device after exiting" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:59 msgid "Key" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:80 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:81 msgid "Key rotation timeout" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:99 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 msgid "Label" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:64 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:67 msgid "Local IP" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:48 msgid "Mode" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:75 msgid "Persist" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 msgid "Port" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:68 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:71 msgid "Remote IP" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:47 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 msgid "Server" msgstr "" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:78 msgid "chacha" msgstr "" diff --git a/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po b/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po index e88aedcbb..14e382bbf 100755 --- a/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po +++ b/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po @@ -1,36 +1,36 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-12-04 16:03+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-05 11:40+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:40 msgid "Advanced Settings" msgstr "高级设置" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:46 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:49 msgid "Client" msgstr "客户端" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:85 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:86 msgid "Clock sync tolerance" msgstr "时钟同步容限" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:95 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:96 msgid "Dynamic rate detection" msgstr "动态速率检测" #: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:42 msgid "Enabled" -msgstr "开启" +msgstr "启用" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:78 msgid "Force fallback cipher" msgstr "强制回退密码" @@ -47,7 +47,7 @@ msgstr "glorytun UDP" msgid "Grant access to glorytun UDP" msgstr "授予访问glorytun UDP的权限" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 msgid "Host" msgstr "主机" @@ -55,54 +55,54 @@ msgstr "主机" msgid "Instances" msgstr "实例" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:60 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:63 msgid "Interface name" msgstr "接口名称" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:90 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:91 msgid "Keep alive timeout" msgstr "保持超时" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:75 msgid "Keep the tunnel device after exiting" msgstr "退出后保留隧道设备" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:59 msgid "Key" msgstr "秘钥" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:80 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:81 msgid "Key rotation timeout" msgstr "秘钥轮换超时" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:99 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 msgid "Label" msgstr "标签" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:64 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:67 msgid "Local IP" msgstr "本地IP" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:48 msgid "Mode" msgstr "模式" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:75 msgid "Persist" msgstr "保持" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 msgid "Port" msgstr "端口" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:68 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:71 msgid "Remote IP" msgstr "远程IP" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:47 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 msgid "Server" msgstr "服务器" -#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:78 msgid "chacha" msgstr "chacha密码" diff --git a/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po~ b/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po~ new file mode 100644 index 000000000..3491db1ab --- /dev/null +++ b/luci-app-glorytun-udp/po/zh_Hans/glorytun-udp.po~ @@ -0,0 +1,108 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:21+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:40 +msgid "Advanced Settings" +msgstr "高级设置" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:46 +msgid "Client" +msgstr "客户端" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:85 +msgid "Clock sync tolerance" +msgstr "时钟同步容限" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:95 +msgid "Dynamic rate detection" +msgstr "动态速率检测" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:42 +msgid "Enabled" +msgstr "开启" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +msgid "Force fallback cipher" +msgstr "强制回退密码" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:39 +msgid "General Settings" +msgstr "通用设置" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:32 +#: luci-app-glorytun-udp/root/usr/share/luci/menu.d/luci-app-glorytun-udp.json:3 +msgid "Glorytun UDP" +msgstr "glorytun UDP" + +#: luci-app-glorytun-udp/root/usr/share/rpcd/acl.d/luci-app-glorytun-udp.json:3 +msgid "Grant access to glorytun UDP" +msgstr "授予访问glorytun UDP的权限" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:50 +msgid "Host" +msgstr "主机" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:34 +msgid "Instances" +msgstr "实例" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:60 +msgid "Interface name" +msgstr "接口名称" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:90 +msgid "Keep alive timeout" +msgstr "保持超时" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +msgid "Keep the tunnel device after exiting" +msgstr "退出后保留隧道设备" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:56 +msgid "Key" +msgstr "秘钥" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:80 +msgid "Key rotation timeout" +msgstr "秘钥轮换超时" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:99 +msgid "Label" +msgstr "标签" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:64 +msgid "Local IP" +msgstr "本地IP" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:45 +msgid "Mode" +msgstr "模式" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:72 +msgid "Persist" +msgstr "保持" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:53 +msgid "Port" +msgstr "端口" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:68 +msgid "Remote IP" +msgstr "远程IP" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:47 +msgid "Server" +msgstr "服务器" + +#: luci-app-glorytun-udp/htdocs/luci-static/resources/view/services/glorytun-udp.js:76 +msgid "chacha" +msgstr "chacha密码" diff --git a/luci-app-iperf/po/de/iperf.po b/luci-app-iperf/po/de/iperf.po index cace2be1b..53023734e 100755 --- a/luci-app-iperf/po/de/iperf.po +++ b/luci-app-iperf/po/de/iperf.po @@ -28,6 +28,10 @@ msgstr "Ungültige Adresse!" msgid "Download" msgstr "Downstream" +#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3 +msgid "Grant UCI access for luci-app-iperf" +msgstr "" + #: luci-app-iperf/luasrc/view/iperf/test.htm:114 msgid "Internet protocol" msgstr "Internet-Protokoll" @@ -53,6 +57,10 @@ msgstr "Die ersten n Sekunden nicht berücksichtigen" msgid "Server" msgstr "Server" +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Server VPS IP is bypassed, so this will test only default route speed." +msgstr "" + #: luci-app-iperf/luasrc/view/iperf/test.htm:102 msgid "Settings" msgstr "Einstellungen" @@ -61,7 +69,7 @@ msgstr "Einstellungen" msgid "Target bitrate (Mbits/s)" msgstr "Angestrebte Bandbreite (MBit/s)" -#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +#: luci-app-iperf/luasrc/view/iperf/test.htm:169 msgid "Test" msgstr "Test" @@ -88,6 +96,7 @@ msgid "Waiting for command to complete..." msgstr "Warte auf Abschluss der Aufgaben" #: luci-app-iperf/luasrc/controller/iperf.lua:8 +#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3 msgid "iPerf" msgstr "iPerf" @@ -95,6 +104,5 @@ msgstr "iPerf" msgid "iPerf speed tests" msgstr "iPerf Geschwindigkeitstests" -#: luci-app-iperf/luasrc/controller/iperf.lua:7 -msgid "iperf" -msgstr "iperf" +#~ msgid "iperf" +#~ msgstr "iperf" diff --git a/luci-app-iperf/po/de/iperf.po~ b/luci-app-iperf/po/de/iperf.po~ new file mode 100644 index 000000000..cace2be1b --- /dev/null +++ b/luci-app-iperf/po/de/iperf.po~ @@ -0,0 +1,100 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-14 08:04+0000\n" +"Last-Translator: Andreas Dorfer \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:128 +msgid "0 for unlimited. Need to be limited for UDP test" +msgstr "" +"für 'unbegrenzt' den Wert '0' setzen. (Muss für UDP-Tests eingeschränkt " +"werden)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Bad address specified!" +msgstr "Ungültige Adresse!" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +#: luci-app-iperf/luasrc/view/iperf/test.htm:78 +#: luci-app-iperf/luasrc/view/iperf/test.htm:83 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Download" +msgstr "Downstream" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:114 +msgid "Internet protocol" +msgstr "Internet-Protokoll" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +msgid "Loading" +msgstr "Wird geladen" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:105 +msgid "Mode of operation" +msgstr "Betriebsart" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:133 +msgid "Number of parallel client streams to run" +msgstr "Anzahl der parallel zu testenden Verbindungen" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:139 +msgid "Omit the first n seconds" +msgstr "Die ersten n Sekunden nicht berücksichtigen" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:151 +msgid "Server" +msgstr "Server" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:102 +msgid "Settings" +msgstr "Einstellungen" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:123 +msgid "Target bitrate (Mbits/s)" +msgstr "Angestrebte Bandbreite (MBit/s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Test" +msgstr "Test" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:100 +msgid "This iPerf interface is in bêta. No support for this." +msgstr "" +"Diesese Oberfläche für iPerf ist im Beta-Stadium und ohne offiziellen " +"Support." + +#: luci-app-iperf/luasrc/view/iperf/test.htm:145 +msgid "Time to transmit for (s)" +msgstr "Übertragungszeit in Sekunden" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:38 +#: luci-app-iperf/luasrc/view/iperf/test.htm:43 +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +msgid "Upload" +msgstr "Upstream" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:27 +#: luci-app-iperf/luasrc/view/iperf/test.htm:67 +msgid "Waiting for command to complete..." +msgstr "Warte auf Abschluss der Aufgaben" + +#: luci-app-iperf/luasrc/controller/iperf.lua:8 +msgid "iPerf" +msgstr "iPerf" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:99 +msgid "iPerf speed tests" +msgstr "iPerf Geschwindigkeitstests" + +#: luci-app-iperf/luasrc/controller/iperf.lua:7 +msgid "iperf" +msgstr "iperf" diff --git a/luci-app-iperf/po/fr/iperf.po b/luci-app-iperf/po/fr/iperf.po index ab1afefd3..6057249da 100755 --- a/luci-app-iperf/po/fr/iperf.po +++ b/luci-app-iperf/po/fr/iperf.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-09-30 08:50+0000\n" +"PO-Revision-Date: 2021-05-21 19:20+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,7 +11,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-iperf/luasrc/view/iperf/test.htm:128 msgid "0 for unlimited. Need to be limited for UDP test" @@ -29,6 +29,10 @@ msgstr "Adresse invalide !" msgid "Download" msgstr "Téléchargement" +#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3 +msgid "Grant UCI access for luci-app-iperf" +msgstr "Accorder l'accès UCI pour luci-app-iperf" + #: luci-app-iperf/luasrc/view/iperf/test.htm:114 msgid "Internet protocol" msgstr "Protocole Internet" @@ -54,6 +58,12 @@ msgstr "Passe les n premières secondes" msgid "Server" msgstr "Serveur" +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Server VPS IP is bypassed, so this will test only default route speed." +msgstr "" +"L'IP du serveur VPS est contournée, donc cela testera uniquement la vitesse " +"de route par défaut." + #: luci-app-iperf/luasrc/view/iperf/test.htm:102 msgid "Settings" msgstr "Paramètres" @@ -62,7 +72,7 @@ msgstr "Paramètres" msgid "Target bitrate (Mbits/s)" msgstr "Vitesse souhaitée (Mbits/s)" -#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +#: luci-app-iperf/luasrc/view/iperf/test.htm:169 msgid "Test" msgstr "Teste" @@ -79,7 +89,7 @@ msgstr "Temps de transmission (s)" #: luci-app-iperf/luasrc/view/iperf/test.htm:43 #: luci-app-iperf/luasrc/view/iperf/test.htm:48 msgid "Upload" -msgstr "Envoie" +msgstr "Téléverser" #: luci-app-iperf/luasrc/view/iperf/test.htm:27 #: luci-app-iperf/luasrc/view/iperf/test.htm:67 @@ -87,6 +97,7 @@ msgid "Waiting for command to complete..." msgstr "En attente de la réponse de la commande..." #: luci-app-iperf/luasrc/controller/iperf.lua:8 +#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3 msgid "iPerf" msgstr "iPerf" @@ -94,6 +105,5 @@ msgstr "iPerf" msgid "iPerf speed tests" msgstr "Tests de vitesse iPerf" -#: luci-app-iperf/luasrc/controller/iperf.lua:7 -msgid "iperf" -msgstr "iperf" +#~ msgid "iperf" +#~ msgstr "iperf" diff --git a/luci-app-iperf/po/fr/iperf.po~ b/luci-app-iperf/po/fr/iperf.po~ new file mode 100644 index 000000000..ab1afefd3 --- /dev/null +++ b/luci-app-iperf/po/fr/iperf.po~ @@ -0,0 +1,99 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2020-09-30 08:50+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:128 +msgid "0 for unlimited. Need to be limited for UDP test" +msgstr "0 pour sans limite. Nécessite d'être limité pour les tests UDP." + +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Bad address specified!" +msgstr "Adresse invalide !" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +#: luci-app-iperf/luasrc/view/iperf/test.htm:78 +#: luci-app-iperf/luasrc/view/iperf/test.htm:83 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Download" +msgstr "Téléchargement" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:114 +msgid "Internet protocol" +msgstr "Protocole Internet" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +msgid "Loading" +msgstr "Chargement" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:105 +msgid "Mode of operation" +msgstr "Mode de fonctionnement" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:133 +msgid "Number of parallel client streams to run" +msgstr "Nombre de client en parallèle" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:139 +msgid "Omit the first n seconds" +msgstr "Passe les n premières secondes" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:151 +msgid "Server" +msgstr "Serveur" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:102 +msgid "Settings" +msgstr "Paramètres" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:123 +msgid "Target bitrate (Mbits/s)" +msgstr "Vitesse souhaitée (Mbits/s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Test" +msgstr "Teste" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:100 +msgid "This iPerf interface is in bêta. No support for this." +msgstr "Cette interface pour iPerf est en bêta. Pas de support pour ça." + +#: luci-app-iperf/luasrc/view/iperf/test.htm:145 +msgid "Time to transmit for (s)" +msgstr "Temps de transmission (s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:38 +#: luci-app-iperf/luasrc/view/iperf/test.htm:43 +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +msgid "Upload" +msgstr "Envoie" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:27 +#: luci-app-iperf/luasrc/view/iperf/test.htm:67 +msgid "Waiting for command to complete..." +msgstr "En attente de la réponse de la commande..." + +#: luci-app-iperf/luasrc/controller/iperf.lua:8 +msgid "iPerf" +msgstr "iPerf" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:99 +msgid "iPerf speed tests" +msgstr "Tests de vitesse iPerf" + +#: luci-app-iperf/luasrc/controller/iperf.lua:7 +msgid "iperf" +msgstr "iperf" diff --git a/luci-app-iperf/po/it/iperf.po b/luci-app-iperf/po/it/iperf.po index 55cef15bd..b8668f2bd 100755 --- a/luci-app-iperf/po/it/iperf.po +++ b/luci-app-iperf/po/it/iperf.po @@ -26,6 +26,10 @@ msgstr "È stato specificato un indirizzo errato!" msgid "Download" msgstr "Scarica" +#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3 +msgid "Grant UCI access for luci-app-iperf" +msgstr "" + #: luci-app-iperf/luasrc/view/iperf/test.htm:114 msgid "Internet protocol" msgstr "Internet Protocol (Protocollo Internet)" @@ -51,6 +55,10 @@ msgstr "Ometti i primi n secondi" msgid "Server" msgstr "Server" +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Server VPS IP is bypassed, so this will test only default route speed." +msgstr "" + #: luci-app-iperf/luasrc/view/iperf/test.htm:102 msgid "Settings" msgstr "Impostazioni" @@ -59,7 +67,7 @@ msgstr "Impostazioni" msgid "Target bitrate (Mbits/s)" msgstr "Bitrate desiderato (Mbits/s)" -#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +#: luci-app-iperf/luasrc/view/iperf/test.htm:169 msgid "Test" msgstr "Test" @@ -84,6 +92,7 @@ msgid "Waiting for command to complete..." msgstr "In attesa del completamento del comando ..." #: luci-app-iperf/luasrc/controller/iperf.lua:8 +#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3 msgid "iPerf" msgstr "iPerf" @@ -91,6 +100,5 @@ msgstr "iPerf" msgid "iPerf speed tests" msgstr "Prove di velocità iPerf" -#: luci-app-iperf/luasrc/controller/iperf.lua:7 -msgid "iperf" -msgstr "iPerf" +#~ msgid "iperf" +#~ msgstr "iPerf" diff --git a/luci-app-iperf/po/it/iperf.po~ b/luci-app-iperf/po/it/iperf.po~ new file mode 100644 index 000000000..55cef15bd --- /dev/null +++ b/luci-app-iperf/po/it/iperf.po~ @@ -0,0 +1,96 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-09-21 12:51+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:128 +msgid "0 for unlimited. Need to be limited for UDP test" +msgstr "0 per illimitato. Deve essere limitato per il test UDP" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Bad address specified!" +msgstr "È stato specificato un indirizzo errato!" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +#: luci-app-iperf/luasrc/view/iperf/test.htm:78 +#: luci-app-iperf/luasrc/view/iperf/test.htm:83 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Download" +msgstr "Scarica" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:114 +msgid "Internet protocol" +msgstr "Internet Protocol (Protocollo Internet)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +msgid "Loading" +msgstr "Caricamento in corso" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:105 +msgid "Mode of operation" +msgstr "Modalità di funzionamento" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:133 +msgid "Number of parallel client streams to run" +msgstr "Numero di flussi client paralleli da eseguire" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:139 +msgid "Omit the first n seconds" +msgstr "Ometti i primi n secondi" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:151 +msgid "Server" +msgstr "Server" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:102 +msgid "Settings" +msgstr "Impostazioni" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:123 +msgid "Target bitrate (Mbits/s)" +msgstr "Bitrate desiderato (Mbits/s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Test" +msgstr "Test" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:100 +msgid "This iPerf interface is in bêta. No support for this." +msgstr "Questa interfaccia iPerf è in bêta." + +#: luci-app-iperf/luasrc/view/iperf/test.htm:145 +msgid "Time to transmit for (s)" +msgstr "È ora di trasmettere per (s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:38 +#: luci-app-iperf/luasrc/view/iperf/test.htm:43 +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +msgid "Upload" +msgstr "Carica" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:27 +#: luci-app-iperf/luasrc/view/iperf/test.htm:67 +msgid "Waiting for command to complete..." +msgstr "In attesa del completamento del comando ..." + +#: luci-app-iperf/luasrc/controller/iperf.lua:8 +msgid "iPerf" +msgstr "iPerf" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:99 +msgid "iPerf speed tests" +msgstr "Prove di velocità iPerf" + +#: luci-app-iperf/luasrc/controller/iperf.lua:7 +msgid "iperf" +msgstr "iPerf" diff --git a/luci-app-iperf/po/oc/iperf.po b/luci-app-iperf/po/oc/iperf.po index 598bb1a2f..f5bc39dad 100755 --- a/luci-app-iperf/po/oc/iperf.po +++ b/luci-app-iperf/po/oc/iperf.po @@ -26,6 +26,10 @@ msgstr "Adreça invalida !" msgid "Download" msgstr "Telecargament" +#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3 +msgid "Grant UCI access for luci-app-iperf" +msgstr "" + #: luci-app-iperf/luasrc/view/iperf/test.htm:114 msgid "Internet protocol" msgstr "Protocòl Internet" @@ -51,6 +55,10 @@ msgstr "Sautar las primièras n segondas" msgid "Server" msgstr "Servidor" +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Server VPS IP is bypassed, so this will test only default route speed." +msgstr "" + #: luci-app-iperf/luasrc/view/iperf/test.htm:102 msgid "Settings" msgstr "Paramètres" @@ -59,7 +67,7 @@ msgstr "Paramètres" msgid "Target bitrate (Mbits/s)" msgstr "Velocitat desirada (Mbits/s)" -#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +#: luci-app-iperf/luasrc/view/iperf/test.htm:169 msgid "Test" msgstr "Pròva" @@ -84,6 +92,7 @@ msgid "Waiting for command to complete..." msgstr "En espèra d’una responsa de la comanda..." #: luci-app-iperf/luasrc/controller/iperf.lua:8 +#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3 msgid "iPerf" msgstr "iPerf" @@ -91,6 +100,5 @@ msgstr "iPerf" msgid "iPerf speed tests" msgstr "Pròva de velocitat iPerf" -#: luci-app-iperf/luasrc/controller/iperf.lua:7 -msgid "iperf" -msgstr "iperf" +#~ msgid "iperf" +#~ msgstr "iperf" diff --git a/luci-app-iperf/po/oc/iperf.po~ b/luci-app-iperf/po/oc/iperf.po~ new file mode 100644 index 000000000..598bb1a2f --- /dev/null +++ b/luci-app-iperf/po/oc/iperf.po~ @@ -0,0 +1,96 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-21 20:21+0000\n" +"Last-Translator: Quentin PAGÈS \n" +"Language-Team: Occitan \n" +"Language: oc\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:128 +msgid "0 for unlimited. Need to be limited for UDP test" +msgstr "0 per cap de limit. Requerís un limit pels ensages UDP" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Bad address specified!" +msgstr "Adreça invalida !" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +#: luci-app-iperf/luasrc/view/iperf/test.htm:78 +#: luci-app-iperf/luasrc/view/iperf/test.htm:83 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Download" +msgstr "Telecargament" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:114 +msgid "Internet protocol" +msgstr "Protocòl Internet" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +msgid "Loading" +msgstr "Cargament" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:105 +msgid "Mode of operation" +msgstr "Mòde de foncionament" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:133 +msgid "Number of parallel client streams to run" +msgstr "Nombre de clients en parallèl" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:139 +msgid "Omit the first n seconds" +msgstr "Sautar las primièras n segondas" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:151 +msgid "Server" +msgstr "Servidor" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:102 +msgid "Settings" +msgstr "Paramètres" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:123 +msgid "Target bitrate (Mbits/s)" +msgstr "Velocitat desirada (Mbits/s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Test" +msgstr "Pròva" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:100 +msgid "This iPerf interface is in bêta. No support for this." +msgstr "Aquesta interfàcia per iPerf es en beta. Cap de support per aquò." + +#: luci-app-iperf/luasrc/view/iperf/test.htm:145 +msgid "Time to transmit for (s)" +msgstr "Temps de transmission (s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:38 +#: luci-app-iperf/luasrc/view/iperf/test.htm:43 +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +msgid "Upload" +msgstr "Mandadís" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:27 +#: luci-app-iperf/luasrc/view/iperf/test.htm:67 +msgid "Waiting for command to complete..." +msgstr "En espèra d’una responsa de la comanda..." + +#: luci-app-iperf/luasrc/controller/iperf.lua:8 +msgid "iPerf" +msgstr "iPerf" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:99 +msgid "iPerf speed tests" +msgstr "Pròva de velocitat iPerf" + +#: luci-app-iperf/luasrc/controller/iperf.lua:7 +msgid "iperf" +msgstr "iperf" diff --git a/luci-app-iperf/po/ru/iperf.po b/luci-app-iperf/po/ru/iperf.po new file mode 100644 index 000000000..402dfb655 --- /dev/null +++ b/luci-app-iperf/po/ru/iperf.po @@ -0,0 +1,104 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:128 +msgid "0 for unlimited. Need to be limited for UDP test" +msgstr "0 - без ограничений. Для теста UDP число должно быть больше 0" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Bad address specified!" +msgstr "Указан не правильный адрес!" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +#: luci-app-iperf/luasrc/view/iperf/test.htm:78 +#: luci-app-iperf/luasrc/view/iperf/test.htm:83 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Download" +msgstr "Получение" + +#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3 +msgid "Grant UCI access for luci-app-iperf" +msgstr "Разрешить доступ к UCI для luci-app-iperf" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:114 +msgid "Internet protocol" +msgstr "Интернет протокол" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +msgid "Loading" +msgstr "Загрузка" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:105 +msgid "Mode of operation" +msgstr "Режим работы" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:133 +msgid "Number of parallel client streams to run" +msgstr "Количество параллельных потоковых клиентов" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:139 +msgid "Omit the first n seconds" +msgstr "Пропустить первые n секунд" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:151 +msgid "Server" +msgstr "Сервер" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Server VPS IP is bypassed, so this will test only default route speed." +msgstr "" +"Включен режим байпаса для IP VPS, будет проверена скорость только маршрута " +"по умолчанию." + +#: luci-app-iperf/luasrc/view/iperf/test.htm:102 +msgid "Settings" +msgstr "Настройки" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:123 +msgid "Target bitrate (Mbits/s)" +msgstr "Целевой битрейт (Mbits/s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:169 +msgid "Test" +msgstr "Тест" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:100 +msgid "This iPerf interface is in bêta. No support for this." +msgstr "Этот iPerf interface в режиме beta. Недоступно." + +#: luci-app-iperf/luasrc/view/iperf/test.htm:145 +msgid "Time to transmit for (s)" +msgstr "Время передачи (s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:38 +#: luci-app-iperf/luasrc/view/iperf/test.htm:43 +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +msgid "Upload" +msgstr "Отправка" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:27 +#: luci-app-iperf/luasrc/view/iperf/test.htm:67 +msgid "Waiting for command to complete..." +msgstr "Ожидание завершения команды..." + +#: luci-app-iperf/luasrc/controller/iperf.lua:8 +#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3 +msgid "iPerf" +msgstr "iPerf" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:99 +msgid "iPerf speed tests" +msgstr "iPerf тест скорости" diff --git a/luci-app-iperf/po/templates/iperf.pot b/luci-app-iperf/po/templates/iperf.pot index 6635e7b7d..8f41376b1 100755 --- a/luci-app-iperf/po/templates/iperf.pot +++ b/luci-app-iperf/po/templates/iperf.pot @@ -17,6 +17,10 @@ msgstr "" msgid "Download" msgstr "" +#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3 +msgid "Grant UCI access for luci-app-iperf" +msgstr "" + #: luci-app-iperf/luasrc/view/iperf/test.htm:114 msgid "Internet protocol" msgstr "" @@ -42,6 +46,10 @@ msgstr "" msgid "Server" msgstr "" +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Server VPS IP is bypassed, so this will test only default route speed." +msgstr "" + #: luci-app-iperf/luasrc/view/iperf/test.htm:102 msgid "Settings" msgstr "" @@ -50,7 +58,7 @@ msgstr "" msgid "Target bitrate (Mbits/s)" msgstr "" -#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +#: luci-app-iperf/luasrc/view/iperf/test.htm:169 msgid "Test" msgstr "" @@ -75,13 +83,10 @@ msgid "Waiting for command to complete..." msgstr "" #: luci-app-iperf/luasrc/controller/iperf.lua:8 +#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3 msgid "iPerf" msgstr "" #: luci-app-iperf/luasrc/view/iperf/test.htm:99 msgid "iPerf speed tests" msgstr "" - -#: luci-app-iperf/luasrc/controller/iperf.lua:7 -msgid "iperf" -msgstr "" diff --git a/luci-app-iperf/po/zh_Hans/iperf.po b/luci-app-iperf/po/zh_Hans/iperf.po index ca33cb025..6ccea7a50 100755 --- a/luci-app-iperf/po/zh_Hans/iperf.po +++ b/luci-app-iperf/po/zh_Hans/iperf.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-12-04 16:02+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-13 21:38+0000\n" +"Last-Translator: justbin <419989953@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-iperf/luasrc/view/iperf/test.htm:128 msgid "0 for unlimited. Need to be limited for UDP test" @@ -17,7 +17,7 @@ msgstr "0代表无限.需要限制UDP测试" #: luci-app-iperf/luasrc/view/iperf/test.htm:48 #: luci-app-iperf/luasrc/view/iperf/test.htm:88 msgid "Bad address specified!" -msgstr "指定的地址错误啊哥们!" +msgstr "指定地址错误!" #: luci-app-iperf/luasrc/view/iperf/test.htm:66 #: luci-app-iperf/luasrc/view/iperf/test.htm:78 @@ -26,6 +26,10 @@ msgstr "指定的地址错误啊哥们!" msgid "Download" msgstr "下载" +#: luci-app-iperf/root/usr/share/rpcd/acl.d/luci-app-iperf.json:3 +msgid "Grant UCI access for luci-app-iperf" +msgstr "授予luci-app-iperf UCI访问权限" + #: luci-app-iperf/luasrc/view/iperf/test.htm:114 msgid "Internet protocol" msgstr "互联网协议" @@ -51,6 +55,10 @@ msgstr "忽略前n秒" msgid "Server" msgstr "服务器" +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Server VPS IP is bypassed, so this will test only default route speed." +msgstr "VPS IP被绕过,因此这将只测试默认的路由速度。" + #: luci-app-iperf/luasrc/view/iperf/test.htm:102 msgid "Settings" msgstr "设置" @@ -59,7 +67,7 @@ msgstr "设置" msgid "Target bitrate (Mbits/s)" msgstr "目标比特率(Mbits/s)" -#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +#: luci-app-iperf/luasrc/view/iperf/test.htm:169 msgid "Test" msgstr "测试" @@ -84,6 +92,7 @@ msgid "Waiting for command to complete..." msgstr "等待命令完成..." #: luci-app-iperf/luasrc/controller/iperf.lua:8 +#: luci-app-iperf/root/usr/share/luci/menu.d/luci-app-iperf.json:3 msgid "iPerf" msgstr "iPerf测速" @@ -91,6 +100,5 @@ msgstr "iPerf测速" msgid "iPerf speed tests" msgstr "iPerf速度测试" -#: luci-app-iperf/luasrc/controller/iperf.lua:7 -msgid "iperf" -msgstr "iperf测速" +#~ msgid "iperf" +#~ msgstr "iperf测速" diff --git a/luci-app-iperf/po/zh_Hans/iperf.po~ b/luci-app-iperf/po/zh_Hans/iperf.po~ new file mode 100644 index 000000000..63ea2e8b8 --- /dev/null +++ b/luci-app-iperf/po/zh_Hans/iperf.po~ @@ -0,0 +1,96 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:03+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:128 +msgid "0 for unlimited. Need to be limited for UDP test" +msgstr "0代表无限.需要限制UDP测试" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Bad address specified!" +msgstr "指定地址错误!" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +#: luci-app-iperf/luasrc/view/iperf/test.htm:78 +#: luci-app-iperf/luasrc/view/iperf/test.htm:83 +#: luci-app-iperf/luasrc/view/iperf/test.htm:88 +msgid "Download" +msgstr "下载" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:114 +msgid "Internet protocol" +msgstr "互联网协议" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:66 +msgid "Loading" +msgstr "载入中" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:105 +msgid "Mode of operation" +msgstr "操作模式" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:133 +msgid "Number of parallel client streams to run" +msgstr "要运行的并行客户端流的数量" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:139 +msgid "Omit the first n seconds" +msgstr "忽略前n秒" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:151 +msgid "Server" +msgstr "服务器" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:102 +msgid "Settings" +msgstr "设置" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:123 +msgid "Target bitrate (Mbits/s)" +msgstr "目标比特率(Mbits/s)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:165 +msgid "Test" +msgstr "测试" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:100 +msgid "This iPerf interface is in bêta. No support for this." +msgstr "此iPerf界面位于测试中.对此不支持." + +#: luci-app-iperf/luasrc/view/iperf/test.htm:145 +msgid "Time to transmit for (s)" +msgstr "传输时间 (秒)" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:26 +#: luci-app-iperf/luasrc/view/iperf/test.htm:38 +#: luci-app-iperf/luasrc/view/iperf/test.htm:43 +#: luci-app-iperf/luasrc/view/iperf/test.htm:48 +msgid "Upload" +msgstr "上传" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:27 +#: luci-app-iperf/luasrc/view/iperf/test.htm:67 +msgid "Waiting for command to complete..." +msgstr "等待命令完成..." + +#: luci-app-iperf/luasrc/controller/iperf.lua:8 +msgid "iPerf" +msgstr "iPerf测速" + +#: luci-app-iperf/luasrc/view/iperf/test.htm:99 +msgid "iPerf speed tests" +msgstr "iPerf速度测试" + +#: luci-app-iperf/luasrc/controller/iperf.lua:7 +msgid "iperf" +msgstr "iperf测速" diff --git a/luci-app-mail/po/de/mail.po b/luci-app-mail/po/de/mail.po index f04c4e7c4..2b7c7984e 100755 --- a/luci-app-mail/po/de/mail.po +++ b/luci-app-mail/po/de/mail.po @@ -10,35 +10,55 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" +#: luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json:3 +msgid "E-Mail" +msgstr "" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:34 msgid "From" msgstr "Von" +#: luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json:3 +msgid "Grant UCI access for luci-app-mail" +msgstr "" + +#: luci-app-mail/luasrc/controller/mail.lua:4 +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Mail settings" msgstr "E-Mail-Einstellungen" +#: luci-app-mail/luasrc/model/cbi/mail.lua:30 msgid "Password" msgstr "Schlüssel" +#: luci-app-mail/luasrc/model/cbi/mail.lua:15 msgid "Port" msgstr "Port" +#: luci-app-mail/luasrc/model/cbi/mail.lua:6 msgid "SMTP" msgstr "SMTP" +#: luci-app-mail/luasrc/model/cbi/mail.lua:24 msgid "STARTTLS" msgstr "StartTLS" +#: luci-app-mail/luasrc/model/cbi/mail.lua:10 msgid "Server" msgstr "Server" +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Set mail settings for services that need to send mails." msgstr "Einstellungen für Dienste, die E-Mail versenden können sollen." +#: luci-app-mail/luasrc/model/cbi/mail.lua:21 msgid "TLS" msgstr "TLS" +#: luci-app-mail/luasrc/model/cbi/mail.lua:39 msgid "To" msgstr "An" +#: luci-app-mail/luasrc/model/cbi/mail.lua:27 msgid "Username" msgstr "Benutzername" diff --git a/luci-app-mail/po/de/mail.po~ b/luci-app-mail/po/de/mail.po~ new file mode 100644 index 000000000..f04c4e7c4 --- /dev/null +++ b/luci-app-mail/po/de/mail.po~ @@ -0,0 +1,44 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-14 08:04+0000\n" +"Last-Translator: Andreas Dorfer \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +msgid "From" +msgstr "Von" + +msgid "Mail settings" +msgstr "E-Mail-Einstellungen" + +msgid "Password" +msgstr "Schlüssel" + +msgid "Port" +msgstr "Port" + +msgid "SMTP" +msgstr "SMTP" + +msgid "STARTTLS" +msgstr "StartTLS" + +msgid "Server" +msgstr "Server" + +msgid "Set mail settings for services that need to send mails." +msgstr "Einstellungen für Dienste, die E-Mail versenden können sollen." + +msgid "TLS" +msgstr "TLS" + +msgid "To" +msgstr "An" + +msgid "Username" +msgstr "Benutzername" diff --git a/luci-app-mail/po/fr/mail.po b/luci-app-mail/po/fr/mail.po index ed30dd37f..78f77d558 100755 --- a/luci-app-mail/po/fr/mail.po +++ b/luci-app-mail/po/fr/mail.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-03 12:39+0000\n" +"PO-Revision-Date: 2021-05-31 18:51+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,39 +11,59 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" +#: luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json:3 +msgid "E-Mail" +msgstr "E-Mail" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:34 msgid "From" msgstr "De" +#: luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json:3 +msgid "Grant UCI access for luci-app-mail" +msgstr "Accorder l'accès UCI pour luci-app-mail" + +#: luci-app-mail/luasrc/controller/mail.lua:4 +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Mail settings" msgstr "Paramètres e-mail" +#: luci-app-mail/luasrc/model/cbi/mail.lua:30 msgid "Password" msgstr "Mot de passe" +#: luci-app-mail/luasrc/model/cbi/mail.lua:15 msgid "Port" msgstr "Port" +#: luci-app-mail/luasrc/model/cbi/mail.lua:6 msgid "SMTP" msgstr "SMTP" +#: luci-app-mail/luasrc/model/cbi/mail.lua:24 msgid "STARTTLS" msgstr "STARTTLS" +#: luci-app-mail/luasrc/model/cbi/mail.lua:10 msgid "Server" msgstr "Serveur" +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Set mail settings for services that need to send mails." msgstr "" "Définissez les paramètres de messagerie pour les services qui doivent " "envoyer des e-mails." +#: luci-app-mail/luasrc/model/cbi/mail.lua:21 msgid "TLS" msgstr "TLS" +#: luci-app-mail/luasrc/model/cbi/mail.lua:39 msgid "To" msgstr "À" +#: luci-app-mail/luasrc/model/cbi/mail.lua:27 msgid "Username" msgstr "Nom d'utilisateur" diff --git a/luci-app-mail/po/fr/mail.po~ b/luci-app-mail/po/fr/mail.po~ new file mode 100644 index 000000000..ed30dd37f --- /dev/null +++ b/luci-app-mail/po/fr/mail.po~ @@ -0,0 +1,49 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2020-08-03 12:39+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +msgid "From" +msgstr "De" + +msgid "Mail settings" +msgstr "Paramètres e-mail" + +msgid "Password" +msgstr "Mot de passe" + +msgid "Port" +msgstr "Port" + +msgid "SMTP" +msgstr "SMTP" + +msgid "STARTTLS" +msgstr "STARTTLS" + +msgid "Server" +msgstr "Serveur" + +msgid "Set mail settings for services that need to send mails." +msgstr "" +"Définissez les paramètres de messagerie pour les services qui doivent " +"envoyer des e-mails." + +msgid "TLS" +msgstr "TLS" + +msgid "To" +msgstr "À" + +msgid "Username" +msgstr "Nom d'utilisateur" diff --git a/luci-app-mail/po/it/mail.po b/luci-app-mail/po/it/mail.po index fd43053e7..684d94dc4 100755 --- a/luci-app-mail/po/it/mail.po +++ b/luci-app-mail/po/it/mail.po @@ -10,35 +10,55 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" +#: luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json:3 +msgid "E-Mail" +msgstr "" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:34 msgid "From" msgstr "Da" +#: luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json:3 +msgid "Grant UCI access for luci-app-mail" +msgstr "" + +#: luci-app-mail/luasrc/controller/mail.lua:4 +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Mail settings" msgstr "Configurazione mail" +#: luci-app-mail/luasrc/model/cbi/mail.lua:30 msgid "Password" msgstr "Password" +#: luci-app-mail/luasrc/model/cbi/mail.lua:15 msgid "Port" msgstr "Porta" +#: luci-app-mail/luasrc/model/cbi/mail.lua:6 msgid "SMTP" msgstr "SMTP" +#: luci-app-mail/luasrc/model/cbi/mail.lua:24 msgid "STARTTLS" msgstr "STARTTLS" +#: luci-app-mail/luasrc/model/cbi/mail.lua:10 msgid "Server" msgstr "Server" +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Set mail settings for services that need to send mails." msgstr "Configurazione del server mail da utilizzare per inviare alert." +#: luci-app-mail/luasrc/model/cbi/mail.lua:21 msgid "TLS" msgstr "TLS" +#: luci-app-mail/luasrc/model/cbi/mail.lua:39 msgid "To" msgstr "A" +#: luci-app-mail/luasrc/model/cbi/mail.lua:27 msgid "Username" msgstr "Username" diff --git a/luci-app-mail/po/it/mail.po~ b/luci-app-mail/po/it/mail.po~ new file mode 100644 index 000000000..fd43053e7 --- /dev/null +++ b/luci-app-mail/po/it/mail.po~ @@ -0,0 +1,44 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-01 10:49+0000\n" +"Last-Translator: Giuseppe Dipierro \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +msgid "From" +msgstr "Da" + +msgid "Mail settings" +msgstr "Configurazione mail" + +msgid "Password" +msgstr "Password" + +msgid "Port" +msgstr "Porta" + +msgid "SMTP" +msgstr "SMTP" + +msgid "STARTTLS" +msgstr "STARTTLS" + +msgid "Server" +msgstr "Server" + +msgid "Set mail settings for services that need to send mails." +msgstr "Configurazione del server mail da utilizzare per inviare alert." + +msgid "TLS" +msgstr "TLS" + +msgid "To" +msgstr "A" + +msgid "Username" +msgstr "Username" diff --git a/luci-app-mail/po/oc/mail.po b/luci-app-mail/po/oc/mail.po index c34bc1d74..a822d14de 100755 --- a/luci-app-mail/po/oc/mail.po +++ b/luci-app-mail/po/oc/mail.po @@ -10,37 +10,57 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.0.4\n" +#: luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json:3 +msgid "E-Mail" +msgstr "" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:34 msgid "From" msgstr "De" +#: luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json:3 +msgid "Grant UCI access for luci-app-mail" +msgstr "" + +#: luci-app-mail/luasrc/controller/mail.lua:4 +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Mail settings" msgstr "Paramètres e-mail" +#: luci-app-mail/luasrc/model/cbi/mail.lua:30 msgid "Password" msgstr "Senhal" +#: luci-app-mail/luasrc/model/cbi/mail.lua:15 msgid "Port" msgstr "Pòrt" +#: luci-app-mail/luasrc/model/cbi/mail.lua:6 msgid "SMTP" msgstr "SMTP" +#: luci-app-mail/luasrc/model/cbi/mail.lua:24 msgid "STARTTLS" msgstr "STARTTLS" +#: luci-app-mail/luasrc/model/cbi/mail.lua:10 msgid "Server" msgstr "Servidor" +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Set mail settings for services that need to send mails." msgstr "" -"Definissètz los paramètres de messatjariá pels servicis que devon enviar " -"d’e-mails." +"Definissètz los paramètres de messatjariá pels servicis que devon enviar d’e-" +"mails." +#: luci-app-mail/luasrc/model/cbi/mail.lua:21 msgid "TLS" msgstr "TLS" +#: luci-app-mail/luasrc/model/cbi/mail.lua:39 msgid "To" msgstr "A" +#: luci-app-mail/luasrc/model/cbi/mail.lua:27 msgid "Username" msgstr "Nom d'utilizaire" diff --git a/luci-app-mail/po/oc/mail.po~ b/luci-app-mail/po/oc/mail.po~ new file mode 100644 index 000000000..ce93d0ed8 --- /dev/null +++ b/luci-app-mail/po/oc/mail.po~ @@ -0,0 +1,46 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-21 20:21+0000\n" +"Last-Translator: Quentin PAGÈS \n" +"Language-Team: Occitan \n" +"Language: oc\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +msgid "From" +msgstr "De" + +msgid "Mail settings" +msgstr "Paramètres e-mail" + +msgid "Password" +msgstr "Senhal" + +msgid "Port" +msgstr "Pòrt" + +msgid "SMTP" +msgstr "SMTP" + +msgid "STARTTLS" +msgstr "STARTTLS" + +msgid "Server" +msgstr "Servidor" + +msgid "Set mail settings for services that need to send mails." +msgstr "" +"Definissètz los paramètres de messatjariá pels servicis que devon enviar d’e-" +"mails." + +msgid "TLS" +msgstr "TLS" + +msgid "To" +msgstr "A" + +msgid "Username" +msgstr "Nom d'utilizaire" diff --git a/luci-app-mail/po/ru/mail.po b/luci-app-mail/po/ru/mail.po new file mode 100644 index 000000000..55fcead70 --- /dev/null +++ b/luci-app-mail/po/ru/mail.po @@ -0,0 +1,65 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-05-13 21:38+0000\n" +"Last-Translator: Aleksandr Serdyukov \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json:3 +msgid "E-Mail" +msgstr "E-Mail" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:34 +msgid "From" +msgstr "От" + +#: luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json:3 +msgid "Grant UCI access for luci-app-mail" +msgstr "Полный UCI доступ для luci-app-mail" + +#: luci-app-mail/luasrc/controller/mail.lua:4 +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 +msgid "Mail settings" +msgstr "Настройки почты" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:30 +msgid "Password" +msgstr "Пароль" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:15 +msgid "Port" +msgstr "Порт" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:6 +msgid "SMTP" +msgstr "SMTP" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:24 +msgid "STARTTLS" +msgstr "STARTTLS" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:10 +msgid "Server" +msgstr "Сервер" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 +msgid "Set mail settings for services that need to send mails." +msgstr "Выбор настроек почты для сервисов, которым нужно отправлять почту." + +#: luci-app-mail/luasrc/model/cbi/mail.lua:21 +msgid "TLS" +msgstr "TLS" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:39 +msgid "To" +msgstr "Кому" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:27 +msgid "Username" +msgstr "Имя пользователя" diff --git a/luci-app-mail/po/templates/mail.pot b/luci-app-mail/po/templates/mail.pot index a2eeddf5c..9abad09a1 100755 --- a/luci-app-mail/po/templates/mail.pot +++ b/luci-app-mail/po/templates/mail.pot @@ -1,35 +1,55 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" +#: luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json:3 +msgid "E-Mail" +msgstr "" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:34 msgid "From" msgstr "" +#: luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json:3 +msgid "Grant UCI access for luci-app-mail" +msgstr "" + +#: luci-app-mail/luasrc/controller/mail.lua:4 +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Mail settings" msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:30 msgid "Password" msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:15 msgid "Port" msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:6 msgid "SMTP" msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:24 msgid "STARTTLS" msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:10 msgid "Server" msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Set mail settings for services that need to send mails." msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:21 msgid "TLS" msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:39 msgid "To" msgstr "" +#: luci-app-mail/luasrc/model/cbi/mail.lua:27 msgid "Username" msgstr "" diff --git a/luci-app-mail/po/zh_Hans/mail.po b/luci-app-mail/po/zh_Hans/mail.po index 1c3a57e2f..f857e08b7 100755 --- a/luci-app-mail/po/zh_Hans/mail.po +++ b/luci-app-mail/po/zh_Hans/mail.po @@ -1,44 +1,64 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-12-04 16:02+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-13 21:38+0000\n" +"Last-Translator: justbin <419989953@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" +#: luci-app-mail/root/usr/share/luci/menu.d/luci-app-mail.json:3 +msgid "E-Mail" +msgstr "电子邮件" + +#: luci-app-mail/luasrc/model/cbi/mail.lua:34 msgid "From" msgstr "来自" +#: luci-app-mail/root/usr/share/rpcd/acl.d/luci-app-mail.json:3 +msgid "Grant UCI access for luci-app-mail" +msgstr "授予luci-app-iperf UCI访问权限" + +#: luci-app-mail/luasrc/controller/mail.lua:4 +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Mail settings" msgstr "邮件设置" +#: luci-app-mail/luasrc/model/cbi/mail.lua:30 msgid "Password" msgstr "密码" +#: luci-app-mail/luasrc/model/cbi/mail.lua:15 msgid "Port" msgstr "端口" +#: luci-app-mail/luasrc/model/cbi/mail.lua:6 msgid "SMTP" msgstr "SMTP设置" +#: luci-app-mail/luasrc/model/cbi/mail.lua:24 msgid "STARTTLS" msgstr "STARTTLS设置" +#: luci-app-mail/luasrc/model/cbi/mail.lua:10 msgid "Server" msgstr "服务器" +#: luci-app-mail/luasrc/model/cbi/mail.lua:4 msgid "Set mail settings for services that need to send mails." msgstr "为需要发送邮件的服务设置邮件设置." +#: luci-app-mail/luasrc/model/cbi/mail.lua:21 msgid "TLS" msgstr "证书" +#: luci-app-mail/luasrc/model/cbi/mail.lua:39 msgid "To" msgstr "发送到" +#: luci-app-mail/luasrc/model/cbi/mail.lua:27 msgid "Username" msgstr "账号" diff --git a/luci-app-mail/po/zh_Hans/mail.po~ b/luci-app-mail/po/zh_Hans/mail.po~ new file mode 100644 index 000000000..1c3a57e2f --- /dev/null +++ b/luci-app-mail/po/zh_Hans/mail.po~ @@ -0,0 +1,44 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-04 16:02+0000\n" +"Last-Translator: antrouter \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.0.4\n" + +msgid "From" +msgstr "来自" + +msgid "Mail settings" +msgstr "邮件设置" + +msgid "Password" +msgstr "密码" + +msgid "Port" +msgstr "端口" + +msgid "SMTP" +msgstr "SMTP设置" + +msgid "STARTTLS" +msgstr "STARTTLS设置" + +msgid "Server" +msgstr "服务器" + +msgid "Set mail settings for services that need to send mails." +msgstr "为需要发送邮件的服务设置邮件设置." + +msgid "TLS" +msgstr "证书" + +msgid "To" +msgstr "发送到" + +msgid "Username" +msgstr "账号" diff --git a/luci-app-mail/po/zh_Hant_HK/mail.po b/luci-app-mail/po/zh_Hant_HK/mail.po deleted file mode 100755 index be68bf858..000000000 --- a/luci-app-mail/po/zh_Hant_HK/mail.po +++ /dev/null @@ -1,38 +0,0 @@ -msgid "" -msgstr "" -"Language: zh_Hant_HK\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "From" -msgstr "" - -msgid "Mail settings" -msgstr "" - -msgid "Password" -msgstr "" - -msgid "Port" -msgstr "" - -msgid "SMTP" -msgstr "" - -msgid "STARTTLS" -msgstr "" - -msgid "Server" -msgstr "" - -msgid "Set mail settings for services that need to send mails." -msgstr "" - -msgid "TLS" -msgstr "" - -msgid "To" -msgstr "" - -msgid "Username" -msgstr "" diff --git a/luci-app-mlvpn/po/fr/mlvpn.po b/luci-app-mlvpn/po/fr/mlvpn.po index cafa645a9..f7ef82ca8 100755 --- a/luci-app-mlvpn/po/fr/mlvpn.po +++ b/luci-app-mlvpn/po/fr/mlvpn.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -14,15 +14,19 @@ msgstr "" msgid "Advanced Settings" msgstr "Configuration avancée" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:38 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:41 msgid "Client" msgstr "Client" +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:75 +msgid "Disable encryption" +msgstr "" + #: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:34 msgid "Enabled" -msgstr "Activé" +msgstr "Activer" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:48 msgid "First Port" msgstr "Premier port" @@ -34,7 +38,7 @@ msgstr "Paramètres généraux" msgid "Grant UCI access for luci-app-mlvpn" msgstr "Accorder l'accès UCI pour luci-app-mlvpn" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 msgid "Host" msgstr "Hôte" @@ -42,15 +46,15 @@ msgstr "Hôte" msgid "Instances" msgstr "Instances" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:54 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:57 msgid "Interface name" msgstr "Nom de l'interface" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:78 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 msgid "Label" msgstr "Étiquette" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:72 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:79 msgid "Loss tolerance" msgstr "Tolérance aux pertes" @@ -59,22 +63,22 @@ msgstr "Tolérance aux pertes" msgid "MLVPN" msgstr "MLVPN" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:40 msgid "Mode" msgstr "Mode" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:50 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:53 msgid "Password" msgstr "Mot de passe" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:66 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:69 msgid "Reorder buffer size" msgstr "Taille du tampon de réordonnancement" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:39 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 msgid "Server" msgstr "Serveur" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:60 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:63 msgid "Timeout (s)" msgstr "Délais d'attente (s)" diff --git a/luci-app-mlvpn/po/fr/mlvpn.po~ b/luci-app-mlvpn/po/fr/mlvpn.po~ new file mode 100644 index 000000000..b8f466284 --- /dev/null +++ b/luci-app-mlvpn/po/fr/mlvpn.po~ @@ -0,0 +1,80 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:32 +msgid "Advanced Settings" +msgstr "Configuration avancée" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:38 +msgid "Client" +msgstr "Client" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:34 +msgid "Enabled" +msgstr "Activer" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 +msgid "First Port" +msgstr "Premier port" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:31 +msgid "General Settings" +msgstr "Paramètres généraux" + +#: luci-app-mlvpn/root/usr/share/rpcd/acl.d/luci-app-mlvpn.json:3 +msgid "Grant UCI access for luci-app-mlvpn" +msgstr "Accorder l'accès UCI pour luci-app-mlvpn" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 +msgid "Host" +msgstr "Hôte" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:26 +msgid "Instances" +msgstr "Instances" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:54 +msgid "Interface name" +msgstr "Nom de l'interface" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:78 +msgid "Label" +msgstr "Étiquette" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:72 +msgid "Loss tolerance" +msgstr "Tolérance aux pertes" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:24 +#: luci-app-mlvpn/root/usr/share/luci/menu.d/luci-app-mlvpn.json:3 +msgid "MLVPN" +msgstr "MLVPN" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 +msgid "Mode" +msgstr "Mode" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:50 +msgid "Password" +msgstr "Mot de passe" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:66 +msgid "Reorder buffer size" +msgstr "Taille du tampon de réordonnancement" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:39 +msgid "Server" +msgstr "Serveur" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:60 +msgid "Timeout (s)" +msgstr "Délais d'attente (s)" diff --git a/luci-app-mlvpn/po/ru/mlvpn.po b/luci-app-mlvpn/po/ru/mlvpn.po new file mode 100644 index 000000000..de9e4cd8c --- /dev/null +++ b/luci-app-mlvpn/po/ru/mlvpn.po @@ -0,0 +1,85 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-05-13 21:38+0000\n" +"Last-Translator: Aleksandr Serdyukov \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:32 +msgid "Advanced Settings" +msgstr "Дополнительные настройки" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:41 +msgid "Client" +msgstr "Клиент" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:75 +msgid "Disable encryption" +msgstr "Отключить шифрование" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:34 +msgid "Enabled" +msgstr "Установлено" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:48 +msgid "First Port" +msgstr "Первый порт" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:31 +msgid "General Settings" +msgstr "Основные настройки" + +#: luci-app-mlvpn/root/usr/share/rpcd/acl.d/luci-app-mlvpn.json:3 +msgid "Grant UCI access for luci-app-mlvpn" +msgstr "Полный UCI доступ для luci-app-mlvpn" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 +msgid "Host" +msgstr "Хост" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:26 +msgid "Instances" +msgstr "Экземпляры" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:57 +msgid "Interface name" +msgstr "Имя интерфейса" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 +msgid "Label" +msgstr "Метка" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:79 +msgid "Loss tolerance" +msgstr "Терпимость к потерям" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:24 +#: luci-app-mlvpn/root/usr/share/luci/menu.d/luci-app-mlvpn.json:3 +msgid "MLVPN" +msgstr "MLVPN" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:40 +msgid "Mode" +msgstr "Режим" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:53 +msgid "Password" +msgstr "Пароль" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:69 +msgid "Reorder buffer size" +msgstr "Изменить размер буфера" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 +msgid "Server" +msgstr "Сервер" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:63 +msgid "Timeout (s)" +msgstr "Тайм- аут (s)" diff --git a/luci-app-mlvpn/po/templates/mlvpn.pot b/luci-app-mlvpn/po/templates/mlvpn.pot index 45e559267..2f1fe9c73 100755 --- a/luci-app-mlvpn/po/templates/mlvpn.pot +++ b/luci-app-mlvpn/po/templates/mlvpn.pot @@ -5,15 +5,19 @@ msgstr "Content-Type: text/plain; charset=UTF-8" msgid "Advanced Settings" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:38 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:41 msgid "Client" msgstr "" +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:75 +msgid "Disable encryption" +msgstr "" + #: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:34 msgid "Enabled" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:48 msgid "First Port" msgstr "" @@ -25,7 +29,7 @@ msgstr "" msgid "Grant UCI access for luci-app-mlvpn" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 msgid "Host" msgstr "" @@ -33,15 +37,15 @@ msgstr "" msgid "Instances" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:54 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:57 msgid "Interface name" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:78 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 msgid "Label" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:72 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:79 msgid "Loss tolerance" msgstr "" @@ -50,22 +54,22 @@ msgstr "" msgid "MLVPN" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:40 msgid "Mode" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:50 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:53 msgid "Password" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:66 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:69 msgid "Reorder buffer size" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:39 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 msgid "Server" msgstr "" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:60 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:63 msgid "Timeout (s)" msgstr "" diff --git a/luci-app-mlvpn/po/zh_Hans/mlvpn.po b/luci-app-mlvpn/po/zh_Hans/mlvpn.po index 868ff2e57..806a7ec76 100755 --- a/luci-app-mlvpn/po/zh_Hans/mlvpn.po +++ b/luci-app-mlvpn/po/zh_Hans/mlvpn.po @@ -1,28 +1,32 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-12-04 16:03+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-13 21:38+0000\n" +"Last-Translator: justbin <419989953@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:32 msgid "Advanced Settings" msgstr "高级设置" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:38 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:41 msgid "Client" msgstr "客户端" +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:75 +msgid "Disable encryption" +msgstr "禁用加密" + #: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:34 msgid "Enabled" -msgstr "开启" +msgstr "启用" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:48 msgid "First Port" msgstr "第一端口" @@ -34,7 +38,7 @@ msgstr "通用设置" msgid "Grant UCI access for luci-app-mlvpn" msgstr "授予UCI访问luci-app-mlvpn的权限" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 msgid "Host" msgstr "主机" @@ -42,15 +46,15 @@ msgstr "主机" msgid "Instances" msgstr "实例" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:54 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:57 msgid "Interface name" msgstr "接口名称" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:78 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 msgid "Label" msgstr "标签" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:72 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:79 msgid "Loss tolerance" msgstr "损失容忍" @@ -59,22 +63,22 @@ msgstr "损失容忍" msgid "MLVPN" msgstr "mlvpn" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:40 msgid "Mode" msgstr "模式" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:50 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:53 msgid "Password" msgstr "密码" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:66 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:69 msgid "Reorder buffer size" msgstr "重新排序缓冲区大小" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:39 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 msgid "Server" msgstr "服务器" -#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:60 +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:63 msgid "Timeout (s)" -msgstr "超时(s)" +msgstr "超时(秒)" diff --git a/luci-app-mlvpn/po/zh_Hans/mlvpn.po~ b/luci-app-mlvpn/po/zh_Hans/mlvpn.po~ new file mode 100644 index 000000000..868ff2e57 --- /dev/null +++ b/luci-app-mlvpn/po/zh_Hans/mlvpn.po~ @@ -0,0 +1,80 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-04 16:03+0000\n" +"Last-Translator: antrouter \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:32 +msgid "Advanced Settings" +msgstr "高级设置" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:38 +msgid "Client" +msgstr "客户端" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:34 +msgid "Enabled" +msgstr "开启" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:45 +msgid "First Port" +msgstr "第一端口" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:31 +msgid "General Settings" +msgstr "通用设置" + +#: luci-app-mlvpn/root/usr/share/rpcd/acl.d/luci-app-mlvpn.json:3 +msgid "Grant UCI access for luci-app-mlvpn" +msgstr "授予UCI访问luci-app-mlvpn的权限" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:42 +msgid "Host" +msgstr "主机" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:26 +msgid "Instances" +msgstr "实例" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:54 +msgid "Interface name" +msgstr "接口名称" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:78 +msgid "Label" +msgstr "标签" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:72 +msgid "Loss tolerance" +msgstr "损失容忍" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:24 +#: luci-app-mlvpn/root/usr/share/luci/menu.d/luci-app-mlvpn.json:3 +msgid "MLVPN" +msgstr "mlvpn" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:37 +msgid "Mode" +msgstr "模式" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:50 +msgid "Password" +msgstr "密码" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:66 +msgid "Reorder buffer size" +msgstr "重新排序缓冲区大小" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:39 +msgid "Server" +msgstr "服务器" + +#: luci-app-mlvpn/htdocs/luci-static/resources/view/services/mlvpn.js:60 +msgid "Timeout (s)" +msgstr "超时(s)" diff --git a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua index fa33e28f2..4b3bdb2b7 100755 --- a/luci-app-mptcp/luasrc/model/cbi/mptcp.lua +++ b/luci-app-mptcp/luasrc/model/cbi/mptcp.lua @@ -9,58 +9,77 @@ m = Map("network", translate("MPTCP"), translate("Networks MPTCP settings. Visit local unameinfo = nixio.uname() or { } s = m:section(TypedSection, "globals") -local mtcpg = s:option(ListValue, "multipath", translate("Multipath TCP")) -mtcpg:value("enable", translate("enable")) -mtcpg:value("disable", translate("disable")) -local mtcpck = s:option(ListValue, "mptcp_checksum", translate("Multipath TCP checksum")) -mtcpck:value(1, translate("enable")) -mtcpck:value(0, translate("disable")) -local mtcpck = s:option(ListValue, "mptcp_debug", translate("Multipath Debug")) -mtcpck:value(1, translate("enable")) -mtcpck:value(0, translate("disable")) -local mtcppm = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager")) -mtcppm:value("default", translate("default")) -mtcppm:value("fullmesh", translate("fullmesh")) -mtcppm:value("ndiffports", translate("ndiffports")) -mtcppm:value("binder", translate("binder")) +o = s:option(ListValue, "multipath", translate("Multipath TCP")) +o:value("enable", translate("enable")) +o:value("disable", translate("disable")) +o = s:option(ListValue, "mptcp_checksum", translate("Multipath TCP checksum")) +o:value(1, translate("enable")) +o:value(0, translate("disable")) +o = s:option(ListValue, "mptcp_debug", translate("Multipath Debug")) +o:value(1, translate("enable")) +o:value(0, translate("disable")) +o = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager"), translate("Default is fullmesh")) +o:value("default", translate("default")) +o:value("fullmesh", "fullmesh") +o:value("ndiffports", "ndiffports") +o:value("binder", "binder") if uname.release:sub(1,4) ~= "4.14" then - mtcppm:value("netlink", translate("Netlink")) + o:value("netlink", translate("Netlink")) end -local mtcpsch = s:option(ListValue, "mptcp_scheduler", translate("Multipath TCP scheduler")) -mtcpsch:value("default", translate("default")) -mtcpsch:value("roundrobin", translate("round-robin")) -mtcpsch:value("redundant", translate("redundant")) +o = s:option(ListValue, "mptcp_scheduler", translate("Multipath TCP scheduler")) +o:value("default", translate("default")) +o:value("roundrobin", "round-robin") +o:value("redundant", "redundant") if uname.release:sub(1,4) ~= "4.14" then - mtcpsch:value("blest", translate("BLEST")) - mtcpsch:value("ecf", translate("ECF")) + o:value("blest", "BLEST") + o:value("ecf", "ECF") end -local mtcpsyn = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SYN retries")) -mtcpsyn.datatype = "uinteger" -mtcpsyn.rmempty = false -local congestion = s:option(ListValue, "congestion", translate("Congestion Control"),translate("Default is cubic")) +o = s:option(Value, "mptcp_syn_retries", translate("Multipath TCP SYN retries")) +o.datatype = "uinteger" +o.rmempty = false +o = s:option(ListValue, "congestion", translate("Congestion Control"),translate("Default is cubic")) local availablecong = sys.exec("sysctl -n net.ipv4.tcp_available_congestion_control | xargs -n1 | sort | xargs") for cong in string.gmatch(availablecong, "[^%s]+") do - congestion:value(cong, translate(cong)) + o:value(cong, translate(cong)) end -local mtcpfm_subflows = s:option(Value, "mptcp_fullmesh_num_subflows", translate("Fullmesh subflows for each pair of IP addresses")) -mtcpfm_subflows.datatype = "uinteger" -mtcpfm_subflows.rmempty = false -local mtcpfm_createonerr = s:option(ListValue, "mptcp_fullmesh_create_on_err", translate("Re-create fullmesh subflows after a timeout")) -mtcpfm_createonerr:value(1, translate("enable")) -mtcpfm_createonerr:value(0, translate("disable")) -local mtcpnd_subflows = s:option(Value, "mptcp_ndiffports_num_subflows", translate("ndiffports subflows number")) -mtcpnd_subflows.datatype = "uinteger" -mtcpnd_subflows.rmempty = false +o = s:option(Value, "mptcp_fullmesh_num_subflows", translate("Fullmesh subflows for each pair of IP addresses")) +o.datatype = "uinteger" +o.rmempty = false +o.default = 1 +--o:depends("mptcp_path_manager","fullmesh") + +o = s:option(ListValue, "mptcp_fullmesh_create_on_err", translate("Re-create fullmesh subflows after a timeout")) +o:value(1, translate("enable")) +o:value(0, translate("disable")) +--o:depends("mptcp_path_manager","fullmesh") + +o = s:option(Value, "mptcp_ndiffports_num_subflows", translate("ndiffports subflows number")) +o.datatype = "uinteger" +o.rmempty = false +o.default = 1 +--o:depends("mptcp_path_manager","ndiffports") + +o = s:option(ListValue, "mptcp_rr_cwnd_limited", translate("Fill the congestion window on all subflows for round robin")) +o:value("Y", translate("enable")) +o:value("N", translate("disable")) +o.default = "Y" +--o:depends("mptcp_scheduler","roundrobin") + +o = s:option(Value, "mptcp_rr_num_segments", translate("Consecutive segments that should be sent for round robin")) +o.datatype = "uinteger" +o.rmempty = false +o.default = 1 +--o:depends("mptcp_scheduler","roundrobin") s = m:section(TypedSection, "interface", translate("Interfaces Settings")) -mptcp = s:option(ListValue, "multipath", translate("Multipath TCP"), translate("One interface must be set as master")) -mptcp:value("on", translate("enabled")) -mptcp:value("off", translate("disabled")) -mptcp:value("master", translate("master")) -mptcp:value("backup", translate("backup")) ---mptcp:value("handover", translate("handover")) -mptcp.default = "off" +o = s:option(ListValue, "multipath", translate("Multipath TCP"), translate("One interface must be set as master")) +o:value("on", translate("enabled")) +o:value("off", translate("disabled")) +o:value("master", translate("master")) +o:value("backup", translate("backup")) +--o:value("handover", translate("handover")) +o.default = "off" return m diff --git a/luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm b/luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm index 3df062637..7cd2a7645 100755 --- a/luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm +++ b/luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm @@ -69,5 +69,7 @@
+
+ <%:If you get "TCPOptionMPTCPCapable [...] Sender's Key" at the end, then MPTCP is supported. If there is a "-TCPOptionMPTCPCapable", then it's blocked.%>
<%+footer%> diff --git a/luci-app-mptcp/po/de/mptcp.po b/luci-app-mptcp/po/de/mptcp.po index 3adc07169..9b8c194ab 100755 --- a/luci-app-mptcp/po/de/mptcp.po +++ b/luci-app-mptcp/po/de/mptcp.po @@ -10,27 +10,23 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:652 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" msgstr "(Fenster von %d Minuten, %d Sekunden Intervall)" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:227 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:228 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 msgid "(%d minutes window, %d seconds interval)" msgstr "(Fenster %d Minunten, %d Sekunden Intervall)" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:284 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:323 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:796 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:806 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 msgid "Average:" msgstr "Durchschnitt:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:34 -msgid "BLEST" -msgstr "Blockierungsvorhersage-Betrieb" - #: luci-app-mptcp/luasrc/controller/mptcp.lua:11 msgid "Bandwidth" msgstr "Bandbreite" @@ -41,27 +37,38 @@ msgstr "" "Prüfung auf transparenten Transport von MPTCP-Paketen zwischen Anschluss und " "Server." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:39 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 msgid "Congestion Control" msgstr "Überlauf-Steuerung" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:280 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 msgid "Current:" msgstr "derzeit:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:39 -msgid "Default is bbr" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#, fuzzy +msgid "Default is cubic" msgstr "Voreinstellung ist 'bbr'" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:772 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#, fuzzy +msgid "Default is fullmesh" +msgstr "Voreinstellung ist 'bbr'" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 msgid "Download:" msgstr "Downstream:" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 msgid "Error" msgstr "Fehler" @@ -69,13 +76,28 @@ msgstr "Fehler" msgid "Established connections" msgstr "aufgebaute Verbindungen" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:44 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "" "Datenströme im vollvermaschter Betrieb für die jeweiligen Gegegenstellen-" "Paare" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:793 +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 msgid "Inbound:" msgstr "Ankommend:" @@ -83,23 +105,25 @@ msgstr "Ankommend:" msgid "Interface" msgstr "Schnittstelle" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:55 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 msgid "Interfaces Settings" msgstr "Anschluss-Einstellungen" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Loading" msgstr "Wird geladen" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:79 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:563 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 msgid "MB/s" msgstr "MByte/s" #: luci-app-mptcp/luasrc/controller/mptcp.lua:9 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 msgid "MPTCP" msgstr "MPTCP" @@ -112,8 +136,12 @@ msgstr "MPTCP Vollvermaschung" msgid "MPTCP Support Check" msgstr "Prüfung auf Transparenz für MPTCP" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:572 +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 msgid "Mbit/s" msgstr "MBit/s" @@ -122,11 +150,11 @@ msgid "Multipath Debug" msgstr "Mehrfachausbreitungspfad-Analyse" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:56 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "Multipath TCP" msgstr "Multipath-TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:36 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 msgid "Multipath TCP SYN retries" msgstr "Multipath TCP SYN Wiederholungen" @@ -156,27 +184,27 @@ msgstr "" "tcp.org/pmwiki.php/Users/ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/" "Users/ConfigureMPTCP (english)." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:56 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "One interface must be set as master" msgstr "Ein Anschluss muss als 'primär' defininiert werden." -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:803 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 msgid "Outbound:" msgstr "Abgehend:" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:288 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:327 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:799 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:809 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 msgid "Peak:" msgstr "Spitze:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Re-create fullmesh subflows after a timeout" msgstr "Wiederverbindungs-Wartezeit der Vollvermaschungs-Verbindungen" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:762 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 msgid "Realtime Traffic" msgstr "Echtzeit-Daten" @@ -189,24 +217,21 @@ msgstr "Einstellungen" msgid "Test" msgstr "Test" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:778 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "Upstream:" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Waiting for command to complete..." msgstr "Warte auf Abschluss der Aufgaben" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:60 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "backup" msgstr "Sicherung" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:25 -msgid "binder" -msgstr "Bindung" - #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 msgid "default" @@ -215,83 +240,86 @@ msgstr "Voreinstellung" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:49 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 msgid "disable" msgstr "ausschalten" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:58 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 msgid "disabled" msgstr "aus" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:48 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 msgid "enable" msgstr "anschalten" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 msgid "enabled" msgstr "an" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:23 -msgid "fullmesh" -msgstr "Vollvermaschung" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:61 -msgid "handover" -msgstr "Übergabe" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:74 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:330 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:558 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:794 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:797 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:800 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:804 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:807 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:810 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 msgid "kB/s" msgstr "kBytes/s" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:83 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:330 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:567 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:794 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:797 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:800 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:804 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:807 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:810 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 msgid "kbit/s" msgstr "kBit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 msgid "master" msgstr "primär" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:24 -msgid "ndiffports" -msgstr "ndiff-Ports" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:51 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 msgid "ndiffports subflows number" msgstr "ndiff-Ports Verbindungs-Nummer" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "redundant" -msgstr "redundant" +#~ msgid "BLEST" +#~ msgstr "Blockierungsvorhersage-Betrieb" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "round-robin" -msgstr "Rundlauf-Verfahren" +#~ msgid "binder" +#~ msgstr "Bindung" + +#~ msgid "fullmesh" +#~ msgstr "Vollvermaschung" + +#~ msgid "handover" +#~ msgstr "Übergabe" + +#~ msgid "ndiffports" +#~ msgstr "ndiff-Ports" + +#~ msgid "redundant" +#~ msgstr "redundant" + +#~ msgid "round-robin" +#~ msgstr "Rundlauf-Verfahren" diff --git a/luci-app-mptcp/po/de/mptcp.po~ b/luci-app-mptcp/po/de/mptcp.po~ new file mode 100644 index 000000000..dd585adf2 --- /dev/null +++ b/luci-app-mptcp/po/de/mptcp.po~ @@ -0,0 +1,327 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-10-05 12:39+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 +msgid "(%d minute window, %d second interval)" +msgstr "(Fenster von %d Minuten, %d Sekunden Intervall)" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 +msgid "(%d minutes window, %d seconds interval)" +msgstr "(Fenster %d Minunten, %d Sekunden Intervall)" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 +msgid "Average:" +msgstr "Durchschnitt:" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 +msgid "Bandwidth" +msgstr "Bandbreite" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 +msgid "Check if MPTCP between interface and server is working." +msgstr "" +"Prüfung auf transparenten Transport von MPTCP-Paketen zwischen Anschluss und " +"Server." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +msgid "Congestion Control" +msgstr "Überlauf-Steuerung" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 +msgid "Current:" +msgstr "derzeit:" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#, fuzzy +#| msgid "Default is bbr" +msgid "Default is cubic" +msgstr "Voreinstellung ist 'bbr'" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#, fuzzy +#| msgid "Default is bbr" +msgid "Default is fullmesh" +msgstr "Voreinstellung ist 'bbr'" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 +msgid "Download:" +msgstr "Downstream:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 +msgid "Error" +msgstr "Fehler" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 +msgid "Established connections" +msgstr "aufgebaute Verbindungen" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +msgid "Fullmesh subflows for each pair of IP addresses" +msgstr "" +"Datenströme im vollvermaschter Betrieb für die jeweiligen Gegegenstellen-" +"Paare" + +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 +msgid "Inbound:" +msgstr "Ankommend:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 +msgid "Interface" +msgstr "Schnittstelle" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +msgid "Interfaces Settings" +msgstr "Anschluss-Einstellungen" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Loading" +msgstr "Wird geladen" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 +msgid "MB/s" +msgstr "MByte/s" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 +msgid "MPTCP Fullmesh" +msgstr "MPTCP Vollvermaschung" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 +msgid "MPTCP Support Check" +msgstr "Prüfung auf Transparenz für MPTCP" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 +msgid "Mbit/s" +msgstr "MBit/s" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 +msgid "Multipath Debug" +msgstr "Mehrfachausbreitungspfad-Analyse" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +msgid "Multipath TCP" +msgstr "Multipath-TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +msgid "Multipath TCP SYN retries" +msgstr "Multipath TCP SYN Wiederholungen" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 +msgid "Multipath TCP checksum" +msgstr "Multipath TCP Prüfummen" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +msgid "Multipath TCP path-manager" +msgstr "Multipath TCP Pfadkontrolle" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +msgid "Multipath TCP scheduler" +msgstr "Multpath TCP Priorisierungskontrolle" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +msgid "Netlink" +msgstr "Netlink-Layer" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +msgid "" +"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" +"ConfigureMPTCP for help." +msgstr "" +"Netzwerk-MPTCP Einstellungen. Dokumentation auf http://multipath-tcp.org/pmwiki.php/" +"Users/ConfigureMPTCP (english)." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +msgid "One interface must be set as master" +msgstr "Ein Anschluss muss als 'primär' defininiert werden." + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 +msgid "Outbound:" +msgstr "Abgehend:" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 +msgid "Peak:" +msgstr "Spitze:" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "Wiederverbindungs-Wartezeit der Vollvermaschungs-Verbindungen" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 +msgid "Realtime Traffic" +msgstr "Echtzeit-Daten" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 +msgid "Settings" +msgstr "Einstellungen" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 +msgid "Test" +msgstr "Test" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 +msgid "Upload:" +msgstr "Upstream:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Waiting for command to complete..." +msgstr "Warte auf Abschluss der Aufgaben" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +msgid "backup" +msgstr "Sicherung" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +msgid "default" +msgstr "Voreinstellung" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +msgid "disable" +msgstr "ausschalten" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +msgid "disabled" +msgstr "aus" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "enable" +msgstr "anschalten" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +msgid "enabled" +msgstr "an" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +msgid "kB/s" +msgstr "kBytes/s" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +msgid "kbit/s" +msgstr "kBit/s" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +msgid "master" +msgstr "primär" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +msgid "ndiffports subflows number" +msgstr "ndiff-Ports Verbindungs-Nummer" + +#~ msgid "BLEST" +#~ msgstr "Blockierungsvorhersage-Betrieb" + +#~ msgid "binder" +#~ msgstr "Bindung" + +#~ msgid "fullmesh" +#~ msgstr "Vollvermaschung" + +#~ msgid "handover" +#~ msgstr "Übergabe" + +#~ msgid "ndiffports" +#~ msgstr "ndiff-Ports" + +#~ msgid "redundant" +#~ msgstr "redundant" + +#~ msgid "round-robin" +#~ msgstr "Rundlauf-Verfahren" diff --git a/luci-app-mptcp/po/fr/mptcp.po b/luci-app-mptcp/po/fr/mptcp.po index f8a44eee9..146ec4466 100755 --- a/luci-app-mptcp/po/fr/mptcp.po +++ b/luci-app-mptcp/po/fr/mptcp.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-10-07 10:57+0000\n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,62 +11,170 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.5.2\n" +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" msgstr "(fenêtre de %d minute, intervalle de %d seconde)" +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 msgid "(%d minutes window, %d seconds interval)" msgstr "(fenêtre de %d minutes, intervalle de %d secondes)" +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 msgid "Average:" msgstr "Moyenne :" +#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 msgid "Bandwidth" msgstr "Bande passante" +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 +msgid "Check if MPTCP between interface and server is working." +msgstr "Vérifiez si MPTCP entre l'interface et le serveur fonctionne." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 msgid "Congestion Control" msgstr "Contrôle de la congestion" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 msgid "Current:" msgstr "Actuellement :" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +msgid "Default is cubic" +msgstr "La valeur par défaut est cubic" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +msgid "Default is fullmesh" +msgstr "La valeur par défaut est fullmesh" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 msgid "Download:" msgstr "Téléchargement :" +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 +msgid "Error" +msgstr "Erreur" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 +msgid "Established connections" +msgstr "Connexions établies" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Sous-flux Fullmesh pour chaque paire d'adresses IP" +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "Accorder l'accès UCI pour luci-app-mlvpn" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" +"Si vous obtenez «TCPOptionMPTCPCapable [...] Sender's Key» à la fin, alors " +"MPTCP est pris en charge. Si il y a \"-TCPOptionMPTCPCapable\", alors il est " +"bloqué." + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 msgid "Inbound:" msgstr "Entrant :" +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 +msgid "Interface" +msgstr "Interface" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 msgid "Interfaces Settings" msgstr "Paramètres des interfaces" +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Loading" +msgstr "Chargement" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 msgid "MB/s" msgstr "Mo/s" +#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 msgid "MPTCP" msgstr "MPTCP" +#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 +msgid "MPTCP Fullmesh" +msgstr "MPTCP Fullmesh" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 +msgid "MPTCP Support Check" +msgstr "Vérification du support MPTCP" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "Surveillance MPTCP" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 msgid "Mbit/s" msgstr "Mbit/s" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 +msgid "Multipath Debug" +msgstr "Débogage multipath" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "Multipath TCP" msgstr "Multipath TCP" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 msgid "Multipath TCP SYN retries" msgstr "Tentatives Multipath TCP SYN" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 msgid "Multipath TCP checksum" msgstr "Somme de contrôle Multipath TCP" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 msgid "Multipath TCP path-manager" msgstr "Gestionnaire de chemins Multipath TCP" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 msgid "Multipath TCP scheduler" msgstr "Planificateur Multipath TCP" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +msgid "Netlink" +msgstr "Netlink" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 msgid "" "Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" @@ -76,74 +184,139 @@ msgstr "" "php/Users/ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/Users/" "ConfigureMPTCP pour de l'aide." +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "One interface must be set as master" msgstr "Une interface doit être configuré en temps que maître" +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 msgid "Outbound:" msgstr "Sortant :" +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 msgid "Peak:" msgstr "Pointe :" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Re-create fullmesh subflows after a timeout" msgstr "Recréer les sous-flux fullmesh après le délai d'expiration" +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 msgid "Realtime Traffic" msgstr "Trafic temps réel" +#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 msgid "Settings" msgstr "Paramètres" +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 +msgid "Test" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "Envoie :" +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Waiting for command to complete..." +msgstr "En attente de la réponse de la commande..." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "backup" msgstr "remplaçant" -msgid "binder" -msgstr "lier" - +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 msgid "default" msgstr "Défaut" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 msgid "disable" msgstr "Désactive" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 msgid "disabled" msgstr "Désactivé" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 msgid "enable" msgstr "Active" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 msgid "enabled" msgstr "Activé" -msgid "fullmesh" -msgstr "fullmesh" - -msgid "handover" -msgstr "relais" - +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 msgid "kB/s" msgstr "Ko/s" +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 msgid "kbit/s" msgstr "kbit/s" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 msgid "master" msgstr "maître" -msgid "ndiffports" -msgstr "ndiffports" - +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 msgid "ndiffports subflows number" msgstr "Nombre de sous-flux ndiffports" -msgid "redundant" -msgstr "redondant" +#~ msgid "binder" +#~ msgstr "lier" -msgid "round-robin" -msgstr "à tour de rôle" +#~ msgid "handover" +#~ msgstr "relais" + +#~ msgid "ndiffports" +#~ msgstr "ndiffports" + +#~ msgid "redundant" +#~ msgstr "redondant" + +#~ msgid "round-robin" +#~ msgstr "à tour de rôle" #~ msgid "Networks MPTCP settings" #~ msgstr "Paramètres réseaux MPTCP" diff --git a/luci-app-mptcp/po/it/mptcp.po b/luci-app-mptcp/po/it/mptcp.po index 272ac94dc..048ef35ef 100755 --- a/luci-app-mptcp/po/it/mptcp.po +++ b/luci-app-mptcp/po/it/mptcp.po @@ -10,27 +10,23 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:779 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" msgstr "(finestra di% d minuti, intervallo di% d secondi)" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:245 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:246 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 msgid "(%d minutes window, %d seconds interval)" msgstr "(finestra di% d minuti, intervallo di% d secondi)" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 msgid "Average:" msgstr "Media:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:34 -msgid "BLEST" -msgstr "BLEST" - #: luci-app-mptcp/luasrc/controller/mptcp.lua:11 msgid "Bandwidth" msgstr "Larghezza banda" @@ -43,27 +39,34 @@ msgstr "Controlla se MPTCP tra l'interfaccia e il server funziona." msgid "Congestion Control" msgstr "Controllo della congestione" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 msgid "Current:" msgstr "Corrente:" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 -msgid "Default is bbr" +#, fuzzy +msgid "Default is cubic" +msgstr "L'impostazione predefinita è bbr" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#, fuzzy +msgid "Default is fullmesh" msgstr "L'impostazione predefinita è bbr" #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 msgid "Download:" msgstr "Scarica:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:35 -msgid "ECF" -msgstr "ECF" - #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 msgid "Error" msgstr "Errore" @@ -71,7 +74,11 @@ msgstr "Errore" msgid "Established connections" msgstr "Connessioni stabilite" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:45 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Flussi secondari fullmesh per ogni coppia di indirizzi IP" @@ -79,6 +86,13 @@ msgstr "Flussi secondari fullmesh per ogni coppia di indirizzi IP" msgid "Grant UCI access for luci-app-mptcp" msgstr "Concedi l'accesso UCI per luci-app-mptcp" +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 msgid "Inbound:" msgstr "In entrata:" @@ -87,18 +101,19 @@ msgstr "In entrata:" msgid "Interface" msgstr "Interfaccia" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:56 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 msgid "Interfaces Settings" msgstr "Impostazioni delle interfacce" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Loading" msgstr "Caricamento in corso" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:90 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 msgid "MB/s" msgstr "MB/s" @@ -117,8 +132,12 @@ msgstr "MPTCP Fullmesh" msgid "MPTCP Support Check" msgstr "Verifica supporto MPTCP" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:99 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:699 +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 msgid "Mbit/s" msgstr "Mbit/s" @@ -127,7 +146,7 @@ msgid "Multipath Debug" msgstr "Debug multipath" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "Multipath TCP" msgstr "Multipath TCP" @@ -158,7 +177,7 @@ msgid "" "ConfigureMPTCP for help." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "One interface must be set as master" msgstr "Un'interfaccia deve essere impostata come master" @@ -166,19 +185,19 @@ msgstr "Un'interfaccia deve essere impostata come master" msgid "Outbound:" msgstr "Upload:" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:323 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:381 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 msgid "Peak:" msgstr "Picco:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:48 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Re-create fullmesh subflows after a timeout" msgstr "Ricrea i flussi secondari fullmesh dopo un timeout" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:895 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 msgid "Realtime Traffic" msgstr "Traffico in tempo reale" @@ -198,17 +217,14 @@ msgstr "Upload:" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Waiting for command to complete..." msgstr "In attesa del completamento del comando ..." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:61 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "backup" msgstr "backup" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:25 -msgid "binder" -msgstr "" - #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 msgid "default" @@ -217,37 +233,35 @@ msgstr "predefinito" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:50 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 msgid "disable" msgstr "disabilita" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 msgid "disabled" msgstr "disabilitato" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:49 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 msgid "enable" msgstr "Attivare" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:58 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 msgid "enabled" msgstr "Abilitato" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:23 -msgid "fullmesh" -msgstr "fullmesh" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:85 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:384 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:685 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 @@ -257,14 +271,14 @@ msgstr "fullmesh" msgid "kB/s" msgstr "kB/s" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:94 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:384 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:694 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 @@ -274,22 +288,28 @@ msgstr "kB/s" msgid "kbit/s" msgstr "kbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:60 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 msgid "master" msgstr "Principale" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:24 -msgid "ndiffports" -msgstr "ndiffports" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 msgid "ndiffports subflows number" msgstr "ndiffports subflows number" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "redundant" -msgstr "ridondante" +#~ msgid "BLEST" +#~ msgstr "BLEST" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "round-robin" -msgstr "round-robin" +#~ msgid "ECF" +#~ msgstr "ECF" + +#~ msgid "fullmesh" +#~ msgstr "fullmesh" + +#~ msgid "ndiffports" +#~ msgstr "ndiffports" + +#~ msgid "redundant" +#~ msgstr "ridondante" + +#~ msgid "round-robin" +#~ msgstr "round-robin" diff --git a/luci-app-mptcp/po/it/mptcp.po~ b/luci-app-mptcp/po/it/mptcp.po~ new file mode 100644 index 000000000..a9bc32b78 --- /dev/null +++ b/luci-app-mptcp/po/it/mptcp.po~ @@ -0,0 +1,317 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-12-01 10:49+0000\n" +"Last-Translator: Giuseppe Dipierro \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 +msgid "(%d minute window, %d second interval)" +msgstr "(finestra di% d minuti, intervallo di% d secondi)" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 +msgid "(%d minutes window, %d seconds interval)" +msgstr "(finestra di% d minuti, intervallo di% d secondi)" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 +msgid "Average:" +msgstr "Media:" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 +msgid "Bandwidth" +msgstr "Larghezza banda" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 +msgid "Check if MPTCP between interface and server is working." +msgstr "Controlla se MPTCP tra l'interfaccia e il server funziona." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +msgid "Congestion Control" +msgstr "Controllo della congestione" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 +msgid "Current:" +msgstr "Corrente:" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#, fuzzy +#| msgid "Default is bbr" +msgid "Default is cubic" +msgstr "L'impostazione predefinita è bbr" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#, fuzzy +#| msgid "Default is bbr" +msgid "Default is fullmesh" +msgstr "L'impostazione predefinita è bbr" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 +msgid "Download:" +msgstr "Scarica:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 +msgid "Error" +msgstr "Errore" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 +msgid "Established connections" +msgstr "Connessioni stabilite" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +msgid "Fullmesh subflows for each pair of IP addresses" +msgstr "Flussi secondari fullmesh per ogni coppia di indirizzi IP" + +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "Concedi l'accesso UCI per luci-app-mptcp" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 +msgid "Inbound:" +msgstr "In entrata:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 +msgid "Interface" +msgstr "Interfaccia" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +msgid "Interfaces Settings" +msgstr "Impostazioni delle interfacce" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Loading" +msgstr "Caricamento in corso" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 +msgid "MB/s" +msgstr "MB/s" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 +msgid "MPTCP Fullmesh" +msgstr "MPTCP Fullmesh" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 +msgid "MPTCP Support Check" +msgstr "Verifica supporto MPTCP" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 +msgid "Multipath Debug" +msgstr "Debug multipath" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +msgid "Multipath TCP" +msgstr "Multipath TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +msgid "Multipath TCP SYN retries" +msgstr "Multipath TCP SYN riprova" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 +msgid "Multipath TCP checksum" +msgstr "Multipath TCP checksum" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +msgid "Multipath TCP path-manager" +msgstr "Multipath TCP path-manager" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +msgid "Multipath TCP scheduler" +msgstr "Multipath TCP scheduler" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +msgid "Netlink" +msgstr "Netlink" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +msgid "" +"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" +"ConfigureMPTCP for help." +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +msgid "One interface must be set as master" +msgstr "Un'interfaccia deve essere impostata come master" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 +msgid "Outbound:" +msgstr "Upload:" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 +msgid "Peak:" +msgstr "Picco:" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "Ricrea i flussi secondari fullmesh dopo un timeout" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 +msgid "Realtime Traffic" +msgstr "Traffico in tempo reale" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 +msgid "Settings" +msgstr "Impostazioni" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 +msgid "Test" +msgstr "Test" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 +msgid "Upload:" +msgstr "Upload:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Waiting for command to complete..." +msgstr "In attesa del completamento del comando ..." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +msgid "backup" +msgstr "backup" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +msgid "default" +msgstr "predefinito" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +msgid "disable" +msgstr "disabilita" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +msgid "disabled" +msgstr "disabilitato" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "enable" +msgstr "Attivare" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +msgid "enabled" +msgstr "Abilitato" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +msgid "kB/s" +msgstr "kB/s" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +msgid "kbit/s" +msgstr "kbit/s" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +msgid "master" +msgstr "Principale" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +msgid "ndiffports subflows number" +msgstr "ndiffports subflows number" + +#~ msgid "BLEST" +#~ msgstr "BLEST" + +#~ msgid "ECF" +#~ msgstr "ECF" + +#~ msgid "fullmesh" +#~ msgstr "fullmesh" + +#~ msgid "ndiffports" +#~ msgstr "ndiffports" + +#~ msgid "redundant" +#~ msgstr "ridondante" + +#~ msgid "round-robin" +#~ msgstr "round-robin" diff --git a/luci-app-mptcp/po/oc/mptcp.po b/luci-app-mptcp/po/oc/mptcp.po index 45a6903a2..3a8ffd4f4 100755 --- a/luci-app-mptcp/po/oc/mptcp.po +++ b/luci-app-mptcp/po/oc/mptcp.po @@ -10,28 +10,23 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:652 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" msgstr "(fenèstra de %d minuta,interval de %d segonda)" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:227 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:228 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 msgid "(%d minutes window, %d seconds interval)" msgstr "(fenèstra de %d minutas,interval de %d segondas)" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:284 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:323 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:796 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:806 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 msgid "Average:" msgstr "Mejana :" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:34 -#, fuzzy -msgid "BLEST" -msgstr "BLEST" - #: luci-app-mptcp/luasrc/controller/mptcp.lua:11 msgid "Bandwidth" msgstr "Benda passanta" @@ -40,27 +35,38 @@ msgstr "Benda passanta" msgid "Check if MPTCP between interface and server is working." msgstr "Verificar se MPTCP entre l‘interfàcia e lo servidor fonciona." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:39 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 msgid "Congestion Control" msgstr "Contraròtle de congestion" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:280 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 msgid "Current:" msgstr "Actualament :" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:39 -msgid "Default is bbr" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#, fuzzy +msgid "Default is cubic" msgstr "Per defaut bbr" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:772 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#, fuzzy +msgid "Default is fullmesh" +msgstr "Per defaut bbr" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 msgid "Download:" msgstr "Telecargament :" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 msgid "Error" msgstr "Error" @@ -68,11 +74,26 @@ msgstr "Error" msgid "Established connections" msgstr "Connexions establidas" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:44 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "Jos flux Fullmesh per cada parelh d’adreças IP" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:793 +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 msgid "Inbound:" msgstr "Dintrant :" @@ -80,23 +101,25 @@ msgstr "Dintrant :" msgid "Interface" msgstr "Interfàcia" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:55 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 msgid "Interfaces Settings" msgstr "Paramètres de las interfàcias" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Loading" msgstr "Cargament" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:79 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:563 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 msgid "MB/s" msgstr "Mo/s" #: luci-app-mptcp/luasrc/controller/mptcp.lua:9 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 msgid "MPTCP" msgstr "MPTCP" @@ -109,8 +132,12 @@ msgstr "MPTCP Fullmesh" msgid "MPTCP Support Check" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:572 +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 msgid "Mbit/s" msgstr "Mbit/s" @@ -119,11 +146,11 @@ msgid "Multipath Debug" msgstr "Desbugatge multipath" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:56 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "Multipath TCP" msgstr "Multipath TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:36 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 msgid "Multipath TCP SYN retries" msgstr "Ensages Multipath TCP SYN" @@ -153,27 +180,27 @@ msgstr "" "Users/ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/Users/" "ConfigureMPTCP per d’ajuda." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:56 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "One interface must be set as master" msgstr "Una interfàcia deu èsser configurada coma principala" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:803 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 msgid "Outbound:" msgstr "Sortent :" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:288 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:327 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:799 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:809 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 msgid "Peak:" msgstr "Punta :" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Re-create fullmesh subflows after a timeout" msgstr "Tornar crear los jos-flus fullmesh aprèp lo relambi d’expiracion" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:762 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 msgid "Realtime Traffic" msgstr "Trafic dirèct" @@ -186,24 +213,21 @@ msgstr "Paramètres" msgid "Test" msgstr "Pròva" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:778 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "Mandadís :" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Waiting for command to complete..." msgstr "En espèra d’una responsa de la comanda..." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:60 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "backup" msgstr "subordinat" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:25 -msgid "binder" -msgstr "associar" - #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 msgid "default" @@ -212,83 +236,87 @@ msgstr "Defaut" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:49 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 msgid "disable" msgstr "desactivar" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:58 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 msgid "disabled" msgstr "desactivat" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:48 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 msgid "enable" msgstr "Activar" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 msgid "enabled" msgstr "Activat" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:23 -msgid "fullmesh" -msgstr "fullmesh" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:61 -msgid "handover" -msgstr "relai" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:74 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:330 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:558 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:794 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:797 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:800 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:804 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:807 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:810 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 msgid "kB/s" msgstr "kB/s" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:83 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:330 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:567 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:794 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:797 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:800 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:804 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:807 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:810 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 msgid "kbit/s" msgstr "kbit/s" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 msgid "master" msgstr "màger" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:24 -msgid "ndiffports" -msgstr "ndiffports" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:51 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 msgid "ndiffports subflows number" msgstr "Nombre de jos-flux ndiffports" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "redundant" -msgstr "redondant" +#, fuzzy +#~ msgid "BLEST" +#~ msgstr "BLEST" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "round-robin" -msgstr "cadun son torn" +#~ msgid "binder" +#~ msgstr "associar" + +#~ msgid "fullmesh" +#~ msgstr "fullmesh" + +#~ msgid "handover" +#~ msgstr "relai" + +#~ msgid "ndiffports" +#~ msgstr "ndiffports" + +#~ msgid "redundant" +#~ msgstr "redondant" + +#~ msgid "round-robin" +#~ msgstr "cadun son torn" diff --git a/luci-app-mptcp/po/oc/mptcp.po~ b/luci-app-mptcp/po/oc/mptcp.po~ new file mode 100644 index 000000000..2ebb121a6 --- /dev/null +++ b/luci-app-mptcp/po/oc/mptcp.po~ @@ -0,0 +1,324 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-10-19 09:37+0000\n" +"Last-Translator: Quentin PAGÈS \n" +"Language-Team: Occitan \n" +"Language: oc\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 +msgid "(%d minute window, %d second interval)" +msgstr "(fenèstra de %d minuta,interval de %d segonda)" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 +msgid "(%d minutes window, %d seconds interval)" +msgstr "(fenèstra de %d minutas,interval de %d segondas)" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 +msgid "Average:" +msgstr "Mejana :" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 +msgid "Bandwidth" +msgstr "Benda passanta" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 +msgid "Check if MPTCP between interface and server is working." +msgstr "Verificar se MPTCP entre l‘interfàcia e lo servidor fonciona." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +msgid "Congestion Control" +msgstr "Contraròtle de congestion" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 +msgid "Current:" +msgstr "Actualament :" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +#, fuzzy +#| msgid "Default is bbr" +msgid "Default is cubic" +msgstr "Per defaut bbr" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +#, fuzzy +#| msgid "Default is bbr" +msgid "Default is fullmesh" +msgstr "Per defaut bbr" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 +msgid "Download:" +msgstr "Telecargament :" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 +msgid "Error" +msgstr "Error" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 +msgid "Established connections" +msgstr "Connexions establidas" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +msgid "Fullmesh subflows for each pair of IP addresses" +msgstr "Jos flux Fullmesh per cada parelh d’adreças IP" + +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 +msgid "Inbound:" +msgstr "Dintrant :" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 +msgid "Interface" +msgstr "Interfàcia" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +msgid "Interfaces Settings" +msgstr "Paramètres de las interfàcias" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Loading" +msgstr "Cargament" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 +msgid "MB/s" +msgstr "Mo/s" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 +msgid "MPTCP Fullmesh" +msgstr "MPTCP Fullmesh" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 +msgid "MPTCP Support Check" +msgstr "" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 +msgid "Multipath Debug" +msgstr "Desbugatge multipath" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +msgid "Multipath TCP" +msgstr "Multipath TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +msgid "Multipath TCP SYN retries" +msgstr "Ensages Multipath TCP SYN" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 +msgid "Multipath TCP checksum" +msgstr "Sòma de contraròtle Multipath TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +msgid "Multipath TCP path-manager" +msgstr "Gestionari dels camins Multipath TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +msgid "Multipath TCP scheduler" +msgstr "Planificator Multipath TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +msgid "Netlink" +msgstr "Ligam ret" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +msgid "" +"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" +"ConfigureMPTCP for help." +msgstr "" +"Paramètres ret MPTCP. Consulatz http://multipath-tcp.org/pmwiki.php/Users/" +"ConfigureMPTCP per d’ajuda." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +msgid "One interface must be set as master" +msgstr "Una interfàcia deu èsser configurada coma principala" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 +msgid "Outbound:" +msgstr "Sortent :" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 +msgid "Peak:" +msgstr "Punta :" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "Tornar crear los jos-flus fullmesh aprèp lo relambi d’expiracion" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 +msgid "Realtime Traffic" +msgstr "Trafic dirèct" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 +msgid "Settings" +msgstr "Paramètres" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 +msgid "Test" +msgstr "Pròva" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 +msgid "Upload:" +msgstr "Mandadís :" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Waiting for command to complete..." +msgstr "En espèra d’una responsa de la comanda..." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +msgid "backup" +msgstr "subordinat" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +msgid "default" +msgstr "Defaut" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +msgid "disable" +msgstr "desactivar" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +msgid "disabled" +msgstr "desactivat" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "enable" +msgstr "Activar" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +msgid "enabled" +msgstr "Activat" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +msgid "kB/s" +msgstr "kB/s" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +msgid "kbit/s" +msgstr "kbit/s" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +msgid "master" +msgstr "màger" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +msgid "ndiffports subflows number" +msgstr "Nombre de jos-flux ndiffports" + +#, fuzzy +#~ msgid "BLEST" +#~ msgstr "BLEST" + +#~ msgid "binder" +#~ msgstr "associar" + +#~ msgid "fullmesh" +#~ msgstr "fullmesh" + +#~ msgid "handover" +#~ msgstr "relai" + +#~ msgid "ndiffports" +#~ msgstr "ndiffports" + +#~ msgid "redundant" +#~ msgstr "redondant" + +#~ msgid "round-robin" +#~ msgstr "cadun son torn" diff --git a/luci-app-mptcp/po/ru/mptcp.po b/luci-app-mptcp/po/ru/mptcp.po new file mode 100644 index 000000000..721602f75 --- /dev/null +++ b/luci-app-mptcp/po/ru/mptcp.po @@ -0,0 +1,301 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 +msgid "(%d minute window, %d second interval)" +msgstr "(% d минутное окно,% d секундный интервал)" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 +msgid "(%d minutes window, %d seconds interval)" +msgstr "(% d минутное окно,% d секундный интервал)" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 +msgid "Average:" +msgstr "Среднее:" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:11 +msgid "Bandwidth" +msgstr "Пропускная способность" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:43 +msgid "Check if MPTCP between interface and server is working." +msgstr "Проверьте, работает ли MPTCP между интерфейсом и сервером." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +msgid "Congestion Control" +msgstr "Контроль перегрузки" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "Последовательные сегменты, которые следует отправлять для round-robin" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 +msgid "Current:" +msgstr "Текущая:" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +msgid "Default is cubic" +msgstr "По умолчанию кубический" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +msgid "Default is fullmesh" +msgstr "По умолчанию - fullmesh" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 +msgid "Download:" +msgstr "Загрузка:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 +msgid "Error" +msgstr "Ошибка" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:18 +msgid "Established connections" +msgstr "Установленные соединения" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "Заполнение окна перегрузки для всех подпотоков для round-robin" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 +msgid "Fullmesh subflows for each pair of IP addresses" +msgstr "Подпотоки Fullmesh для каждой пары IP-адресов" + +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "Предоставить доступ UCI для luci-app-mptcp" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" +"Если в конце вы получите «TCPOptionMPTCPCapable [...] Sender's Key», то " +"MPTCP поддерживается. Если \"-TCPOptionMPTCPCapable\", то MPTCP заблокирован." + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 +msgid "Inbound:" +msgstr "Входящий:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:48 +msgid "Interface" +msgstr "Интерфейс" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 +msgid "Interfaces Settings" +msgstr "Настройки интерфейсов" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Loading" +msgstr "Загрузка" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 +msgid "MB/s" +msgstr "MB/s" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:9 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 +msgid "MPTCP" +msgstr "MPTCP" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:16 +msgid "MPTCP Fullmesh" +msgstr "MPTCP Fullmesh" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:14 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:42 +msgid "MPTCP Support Check" +msgstr "Проверка поддержки MPTCP" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "Мониторинг MPTCP" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 +msgid "Multipath Debug" +msgstr "Многоуровневая отладка" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +msgid "Multipath TCP" +msgstr "Многопоточный TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 +msgid "Multipath TCP SYN retries" +msgstr "Попытки многопоточной TCP SYN" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:15 +msgid "Multipath TCP checksum" +msgstr "Контрольная сумма многопоточного TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +msgid "Multipath TCP path-manager" +msgstr "Многопоточный TCP менеджер" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:29 +msgid "Multipath TCP scheduler" +msgstr "Планировщик многопоточного TCP" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:27 +msgid "Netlink" +msgstr "Netlink" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +msgid "" +"Networks MPTCP settings. Visit http://multipath-tcp.org/pmwiki.php/Users/" +"ConfigureMPTCP for help." +msgstr "" +"Настройки сети MPTCP. Посетите http://multipath-tcp.org/pmwiki.php/Users/" +"ConfigureMPTCP для справки." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 +msgid "One interface must be set as master" +msgstr "Один интерфейс должен быть установлен как главный" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 +msgid "Outbound:" +msgstr "Отправка:" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 +msgid "Peak:" +msgstr "Пиковое значение:" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +msgid "Re-create fullmesh subflows after a timeout" +msgstr "Повторно создать подпотоки fullmesh после тайм-аута" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 +msgid "Realtime Traffic" +msgstr "Трафик в реальном времени" + +#: luci-app-mptcp/luasrc/controller/mptcp.lua:10 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:45 +msgid "Settings" +msgstr "Настройки" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:65 +msgid "Test" +msgstr "Тест" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 +msgid "Upload:" +msgstr "Отправка:" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 +msgid "Waiting for command to complete..." +msgstr "Ожидание завершения команды..." + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 +msgid "backup" +msgstr "Резервирование" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 +msgid "default" +msgstr "По умолчанию" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 +msgid "disable" +msgstr "отключить" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 +msgid "disabled" +msgstr "отключить" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 +msgid "enable" +msgstr "включить" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 +msgid "enabled" +msgstr "Установлено" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +msgid "kB/s" +msgstr "kB/s" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 +msgid "kbit/s" +msgstr "kbit/s" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 +msgid "master" +msgstr "мастер" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +msgid "ndiffports subflows number" +msgstr "количество подпотоков ndiffports" diff --git a/luci-app-mptcp/po/templates/mptcp.pot b/luci-app-mptcp/po/templates/mptcp.pot index f784674a3..770f34333 100755 --- a/luci-app-mptcp/po/templates/mptcp.pot +++ b/luci-app-mptcp/po/templates/mptcp.pot @@ -1,27 +1,23 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:779 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:245 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:246 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 msgid "(%d minutes window, %d seconds interval)" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 msgid "Average:" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:34 -msgid "BLEST" -msgstr "" - #: luci-app-mptcp/luasrc/controller/mptcp.lua:11 msgid "Bandwidth" msgstr "" @@ -34,27 +30,32 @@ msgstr "" msgid "Congestion Control" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 msgid "Current:" msgstr "" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 -msgid "Default is bbr" +msgid "Default is cubic" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +msgid "Default is fullmesh" msgstr "" #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 msgid "Download:" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:35 -msgid "ECF" -msgstr "" - #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 msgid "Error" msgstr "" @@ -62,7 +63,11 @@ msgstr "" msgid "Established connections" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:45 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "" @@ -70,6 +75,13 @@ msgstr "" msgid "Grant UCI access for luci-app-mptcp" msgstr "" +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" + #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 msgid "Inbound:" msgstr "" @@ -78,18 +90,19 @@ msgstr "" msgid "Interface" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:56 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 msgid "Interfaces Settings" msgstr "" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Loading" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:90 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 msgid "MB/s" msgstr "" @@ -108,8 +121,12 @@ msgstr "" msgid "MPTCP Support Check" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:99 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:699 +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 msgid "Mbit/s" msgstr "" @@ -118,7 +135,7 @@ msgid "Multipath Debug" msgstr "" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "Multipath TCP" msgstr "" @@ -149,7 +166,7 @@ msgid "" "ConfigureMPTCP for help." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "One interface must be set as master" msgstr "" @@ -157,19 +174,19 @@ msgstr "" msgid "Outbound:" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:323 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:381 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 msgid "Peak:" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:48 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Re-create fullmesh subflows after a timeout" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:895 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 msgid "Realtime Traffic" msgstr "" @@ -189,17 +206,14 @@ msgstr "" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Waiting for command to complete..." msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:61 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "backup" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:25 -msgid "binder" -msgstr "" - #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 msgid "default" @@ -208,37 +222,35 @@ msgstr "" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:50 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 msgid "disable" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 msgid "disabled" msgstr "" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:49 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 msgid "enable" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:58 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 msgid "enabled" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:23 -msgid "fullmesh" -msgstr "" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:85 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:384 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:685 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 @@ -248,14 +260,14 @@ msgstr "" msgid "kB/s" msgstr "" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:94 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:384 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:694 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 @@ -265,22 +277,10 @@ msgstr "" msgid "kbit/s" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:60 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 msgid "master" msgstr "" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:24 -msgid "ndiffports" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 msgid "ndiffports subflows number" msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "redundant" -msgstr "" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "round-robin" -msgstr "" diff --git a/luci-app-mptcp/po/zh_Hans/mptcp.po b/luci-app-mptcp/po/zh_Hans/mptcp.po index db45787bd..6b16ddad4 100755 --- a/luci-app-mptcp/po/zh_Hans/mptcp.po +++ b/luci-app-mptcp/po/zh_Hans/mptcp.po @@ -1,36 +1,32 @@ msgid "" msgstr "" -"PO-Revision-Date: 2021-02-13 08:01+0000\n" -"Last-Translator: wysh \n" +"PO-Revision-Date: 2021-06-02 09:51+0000\n" +"Last-Translator: antrouter \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:652 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:775 msgid "(%d minute window, %d second interval)" msgstr "(%d 分钟刷新, %d 秒钟刷新)" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:227 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:228 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:241 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:242 msgid "(%d minutes window, %d seconds interval)" msgstr "(%d 分钟间隔, %d 秒钟刷新)" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:284 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:323 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:796 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:806 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:315 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:373 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:932 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:942 msgid "Average:" msgstr "平均:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:34 -msgid "BLEST" -msgstr "最好的" - #: luci-app-mptcp/luasrc/controller/mptcp.lua:11 msgid "Bandwidth" msgstr "带宽" @@ -39,27 +35,36 @@ msgstr "带宽" msgid "Check if MPTCP between interface and server is working." msgstr "检查接口和服务器之间的MPTCP是否正常工作." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:39 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 msgid "Congestion Control" msgstr "阻塞控制" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:280 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:69 +msgid "Consecutive segments that should be sent for round robin" +msgstr "连续轮播应发送的连续段" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:311 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:369 msgid "Current:" msgstr "实时:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:39 -msgid "Default is bbr" -msgstr "默认设置bbr" +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:40 +msgid "Default is cubic" +msgstr "默认设置 cubic" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:772 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:21 +msgid "Default is fullmesh" +msgstr "默认设置fullmesh" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:908 msgid "Download:" msgstr "下载:" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:31 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:31 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:24 msgid "Error" msgstr "错误" @@ -67,11 +72,28 @@ msgstr "错误" msgid "Established connections" msgstr "建立的连接" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:44 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:63 +msgid "Fill the congestion window on all subflows for round robin" +msgstr "在循环的所有子流上填充拥塞窗口" + +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:46 msgid "Fullmesh subflows for each pair of IP addresses" msgstr "每对IP地址的全网格子流" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:793 +#: luci-app-mptcp/root/usr/share/rpcd/acl.d/luci-app-mptcp.json:3 +msgid "Grant UCI access for luci-app-mptcp" +msgstr "授予UCI访问luci-app-mptcp的权限" + +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:73 +msgid "" +"If you get \"TCPOptionMPTCPCapable [...] Sender's Key\" at the end, then " +"MPTCP is supported. If there is a \"-TCPOptionMPTCPCapable\", then it's " +"blocked." +msgstr "" +"如果最后得到“ TCPOptionMPTCPCapable发件人的密钥”,则支持MPTCP。unesdoc.unesco.org " +"unesdoc.unesco.org 如果存在“ -TCPOptionMPTCPCapable”,则将其阻止。" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:929 msgid "Inbound:" msgstr "入站:" @@ -79,25 +101,27 @@ msgstr "入站:" msgid "Interface" msgstr "接口" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:55 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:75 msgid "Interfaces Settings" msgstr "网卡设置" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Loading" msgstr "载入中" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:79 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:563 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:93 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:686 msgid "MB/s" msgstr "MB/s" #: luci-app-mptcp/luasrc/controller/mptcp.lua:9 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:7 +#: luci-app-mptcp/root/usr/share/luci/menu.d/luci-app-mptcp.json:3 msgid "MPTCP" -msgstr "聚合" +msgstr "MPTCP" #: luci-app-mptcp/luasrc/controller/mptcp.lua:16 msgid "MPTCP Fullmesh" @@ -108,21 +132,25 @@ msgstr "设置MPTCP全网" msgid "MPTCP Support Check" msgstr "MPTCP支持检查" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:572 +#: luci-app-mptcp/luasrc/controller/mptcp.lua:20 +msgid "MPTCP monitoring" +msgstr "MPTCP监控" + +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:102 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:695 msgid "Mbit/s" -msgstr "Mbit/秒" +msgstr "Mbit/s" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:18 msgid "Multipath Debug" msgstr "Multipath 调试" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:12 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:56 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "Multipath TCP" msgstr "多路径TCP" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:36 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:37 msgid "Multipath TCP SYN retries" msgstr "多路径 TCP SYN 重试" @@ -149,30 +177,30 @@ msgid "" "ConfigureMPTCP for help." msgstr "" "网络MPTCP设置. 访问http://multipath-tcp.org/pmwiki.php/Users/ConfigureMPTCP4" -" 获取更多的支持." +"ConfigureMPTCP'>http://multipath-tcp.org/pmwiki.php/Users/ConfigureMPTCP4 获取更多的支持." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:56 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:76 msgid "One interface must be set as master" -msgstr "蚂蚁提醒您必须设置一个网卡为主接口" +msgstr "必须设置一个网卡为主接口" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:803 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:939 msgid "Outbound:" msgstr "出站:" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:288 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:327 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:799 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:809 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:319 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:377 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:935 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:945 msgid "Peak:" msgstr "峰值:" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:47 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:52 msgid "Re-create fullmesh subflows after a timeout" msgstr "超时后重新创建全网格子流" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:762 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:891 msgid "Realtime Traffic" msgstr "实时流量" @@ -185,24 +213,21 @@ msgstr "设置" msgid "Test" msgstr "测试" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:778 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:914 msgid "Upload:" msgstr "上传:" #: luci-app-mptcp/luasrc/view/mptcp/mptcp_check.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_connections.htm:21 #: luci-app-mptcp/luasrc/view/mptcp/mptcp_fullmesh.htm:21 +#: luci-app-mptcp/luasrc/view/mptcp/mptcp_monitor.htm:14 msgid "Waiting for command to complete..." msgstr "等待命令完成..." -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:60 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:80 msgid "backup" msgstr "备份" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:25 -msgid "binder" -msgstr "设置binder" - #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:22 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:30 msgid "default" @@ -211,83 +236,86 @@ msgstr "默认" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:14 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:17 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:20 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:49 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:54 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:65 msgid "disable" msgstr "禁用" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:58 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:78 msgid "disabled" msgstr "禁用" #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:13 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:16 #: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:19 -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:48 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:53 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:64 msgid "enable" msgstr "启用" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:77 msgid "enabled" msgstr "启用" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:23 -msgid "fullmesh" -msgstr "全网" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:61 -msgid "handover" -msgstr "移除" - -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:74 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:88 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:330 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:558 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:794 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:797 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:800 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:804 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:807 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:810 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:681 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 msgid "kB/s" msgstr "kB/秒" -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:83 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:283 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:287 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:291 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:97 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:314 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:318 #: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:322 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:326 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:330 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:567 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:794 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:797 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:800 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:804 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:807 -#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:810 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:372 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:376 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:380 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:690 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:930 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:933 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:936 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:940 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:943 +#: luci-app-mptcp/luasrc/view/mptcp/multipath.htm:946 msgid "kbit/s" msgstr "kbit/秒" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:59 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:79 msgid "master" msgstr "主" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:24 -msgid "ndiffports" -msgstr "设置ndiffports" - -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:51 +#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:57 msgid "ndiffports subflows number" msgstr "ndiffports子流数" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:32 -msgid "redundant" -msgstr "冗余" +#~ msgid "BLEST" +#~ msgstr "最好的" -#: luci-app-mptcp/luasrc/model/cbi/mptcp.lua:31 -msgid "round-robin" -msgstr "轮询" +#~ msgid "binder" +#~ msgstr "设置binder" + +#~ msgid "fullmesh" +#~ msgstr "全网" + +#~ msgid "handover" +#~ msgstr "移除" + +#~ msgid "ndiffports" +#~ msgstr "设置ndiffports" + +#~ msgid "redundant" +#~ msgstr "冗余" + +#~ msgid "round-robin" +#~ msgstr "轮询" diff --git a/luci-app-omr-bypass/po/de/omr-bypass.po b/luci-app-omr-bypass/po/de/omr-bypass.po index 659b03508..ae3c0f8dd 100755 --- a/luci-app-omr-bypass/po/de/omr-bypass.po +++ b/luci-app-omr-bypass/po/de/omr-bypass.po @@ -10,113 +10,153 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:64 -msgid "MAC-Address" -msgstr "MAC-Addresse" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:100 -msgid "ASN" -msgstr "ASN" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:52 -msgid "ALL" -msgstr "ALLE" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:105 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 msgid "ASN" msgstr "ASN" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:9 -msgid "Bypass" -msgstr "Ausnahmeregel" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:150 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:151 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:152 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:153 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:154 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:155 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:156 -msgid "Default" -msgstr "Voreinstellung" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:16 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 msgid "Domain" msgstr "Domain" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:11 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:26 msgid "Domains" msgstr "Domains" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:9 -msgid "" -"Here you can bypass ShadowSocks and VPN. If you set Interface to Default " -"this use any working interface." +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" msgstr "" -"Her können Ausnahmen für ShadowSocks und VPN eingetragen werden. Wird als " -"Schnittstelle 'Voreinstellung' gewählt, wird eine beliebige gerade " -"funktionsfähige gewählt (Load Balancing)." -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:31 +#: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 +msgid "Grant access to ndpi resources" +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 msgid "IP" msgstr "IP" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:90 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 msgid "IP Address" msgstr "IP Adresse" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:26 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 msgid "IPs and Networks" msgstr "IPs und Netzwerke" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:21 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:36 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:59 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:80 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:95 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:109 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 msgid "Interface" msgstr "Schnittstelle" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:24 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:39 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:62 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:83 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:98 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:112 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:140 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 +#, fuzzy +msgid "MAC-Address" +msgstr "Quell-MAC-Adresse" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 msgid "Note" msgstr "Bemerkung" -#: luci-app-omr-bypass/luasrc/controller/omr-bypass.lua:6 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +#: luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json:3 msgid "OMR-Bypass" msgstr "OMR-Ausnahmeregel" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +msgid "OpenMPTCProuter IP must be used as DNS." +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 msgid "Ports destination" msgstr "Ziel-Port" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:51 -msgid "Protocol" -msgstr "Protokoll" +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 +msgid "Ports source" +msgstr "" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:119 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 msgid "Protocol/Service" msgstr "Protokoll/Dienst" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:114 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 msgid "Protocols and services" msgstr "Protokolle und Dienste" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:69 -msgid "Source MAC-Address" -msgstr "Quell-MAC-Adresse" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:85 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 msgid "Source lan IP address or network" msgstr "LAN-IP oder CIDR-Netzwerk der Quelleadresse" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:47 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +msgid "When none selected, MPTCP master interface is used." +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 msgid "port" msgstr "Port" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 +#, fuzzy +msgid "protocol" +msgstr "Protokoll" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 +#, fuzzy +msgid "source MAC-Address" +msgstr "Quell-MAC-Adresse" + +#~ msgid "MAC-Address" +#~ msgstr "MAC-Addresse" + +#~ msgid "ASN" +#~ msgstr "ASN" + +#~ msgid "ALL" +#~ msgstr "ALLE" + +#~ msgid "Bypass" +#~ msgstr "Ausnahmeregel" + +#~ msgid "Default" +#~ msgstr "Voreinstellung" + +#~ msgid "" +#~ "Here you can bypass ShadowSocks and VPN. If you set Interface to Default " +#~ "this use any working interface." +#~ msgstr "" +#~ "Her können Ausnahmen für ShadowSocks und VPN eingetragen werden. Wird als " +#~ "Schnittstelle 'Voreinstellung' gewählt, wird eine beliebige gerade " +#~ "funktionsfähige gewählt (Load Balancing)." diff --git a/luci-app-omr-bypass/po/de/omr-bypass.po~ b/luci-app-omr-bypass/po/de/omr-bypass.po~ new file mode 100644 index 000000000..188cfb056 --- /dev/null +++ b/luci-app-omr-bypass/po/de/omr-bypass.po~ @@ -0,0 +1,165 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-10-05 12:39+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 +msgid "ASN" +msgstr "ASN" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 +msgid "Domain" +msgstr "Domain" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:26 +msgid "Domains" +msgstr "Domains" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" +msgstr "" + +#: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 +msgid "Grant access to ndpi resources" +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 +msgid "IP" +msgstr "IP" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 +msgid "IP Address" +msgstr "IP Adresse" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 +msgid "IPs and Networks" +msgstr "IPs und Netzwerke" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "Interface" +msgstr "Schnittstelle" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 +#, fuzzy +#| msgid "Source MAC-Address" +msgid "MAC-Address" +msgstr "Quell-MAC-Adresse" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 +msgid "Note" +msgstr "Bemerkung" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +#: luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json:3 +msgid "OMR-Bypass" +msgstr "OMR-Ausnahmeregel" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +msgid "OpenMPTCProuter IP must be used as DNS." +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 +msgid "Ports destination" +msgstr "Ziel-Port" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 +msgid "Ports source" +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 +msgid "Protocol/Service" +msgstr "Protokoll/Dienst" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 +msgid "Protocols and services" +msgstr "Protokolle und Dienste" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 +msgid "Source lan IP address or network" +msgstr "LAN-IP oder CIDR-Netzwerk der Quelleadresse" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +msgid "When none selected, MPTCP master interface is used." +msgstr "" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 +msgid "port" +msgstr "Port" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 +#, fuzzy +#| msgid "Protocol" +msgid "protocol" +msgstr "Protokoll" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 +#, fuzzy +#| msgid "Source MAC-Address" +msgid "source MAC-Address" +msgstr "Quell-MAC-Adresse" + +#~ msgid "MAC-Address" +#~ msgstr "MAC-Addresse" + +#~ msgid "ASN" +#~ msgstr "ASN" + +#~ msgid "ALL" +#~ msgstr "ALLE" + +#~ msgid "Bypass" +#~ msgstr "Ausnahmeregel" + +#~ msgid "Default" +#~ msgstr "Voreinstellung" + +#~ msgid "" +#~ "Here you can bypass ShadowSocks and VPN. If you set Interface to Default " +#~ "this use any working interface." +#~ msgstr "" +#~ "Her können Ausnahmen für ShadowSocks und VPN eingetragen werden. Wird als " +#~ "Schnittstelle 'Voreinstellung' gewählt, wird eine beliebige gerade " +#~ "funktionsfähige gewählt (Load Balancing)." diff --git a/luci-app-omr-bypass/po/fr/omr-bypass.po b/luci-app-omr-bypass/po/fr/omr-bypass.po index 1370c6f88..272fe4b31 100755 --- a/luci-app-omr-bypass/po/fr/omr-bypass.po +++ b/luci-app-omr-bypass/po/fr/omr-bypass.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-03 12:39+0000\n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,118 +11,160 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.5.2\n" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:64 -msgid "MAC-Address" -msgstr "Adresse MAC" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:100 -msgid "ASN" -msgstr "ASN" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:52 -msgid "ALL" -msgstr "TOUT" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:105 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 msgid "ASN" msgstr "ASN" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:9 -msgid "Bypass" -msgstr "Contourne" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:150 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:151 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:152 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:153 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:154 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:155 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:156 -msgid "Default" -msgstr "Défaut" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:16 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 msgid "Domain" msgstr "Domaine" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:11 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:26 msgid "Domains" msgstr "Domaines" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:9 -msgid "" -"Here you can bypass ShadowSocks and VPN. If you set Interface to Default " -"this use any working interface." -msgstr "" -"Ici vous pouvez contouner Shadowsocks et le VPN. Si vous mettez l'interface " -"à défaut, ça utilisera n'importe qu'elle interface fonctionnant." +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" +msgstr "Activer" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:31 +#: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 +msgid "Grant access to ndpi resources" +msgstr "Accorder l'accès aux ressources ndpi" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 msgid "IP" msgstr "IP" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:90 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 msgid "IP Address" msgstr "Adresse IP" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:26 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 msgid "IPs and Networks" msgstr "IPs et réseaux" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:21 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:36 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:59 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:80 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:95 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:109 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 msgid "Interface" msgstr "Interface" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:24 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:39 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:62 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:83 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:98 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:112 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:140 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 +msgid "MAC-Address" +msgstr "Adresse MAC" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 msgid "Note" msgstr "Note" -#: luci-app-omr-bypass/luasrc/controller/omr-bypass.lua:6 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +#: luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json:3 msgid "OMR-Bypass" msgstr "OMR-Bypass" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +msgid "OpenMPTCProuter IP must be used as DNS." +msgstr "L'IP d'OpenMPTCProuter doit être utilisée comme DNS." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 msgid "Ports destination" msgstr "Ports de destination" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:51 -msgid "Protocol" -msgstr "Protocole" +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 +msgid "Ports source" +msgstr "" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:119 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 msgid "Protocol/Service" msgstr "Protocole/Service" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:114 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 msgid "Protocols and services" msgstr "Protocoles et services" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:69 -msgid "Source MAC-Address" -msgstr "Adresse MAC source" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:85 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 msgid "Source lan IP address or network" msgstr "Adresse IP source ou réseau" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:47 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "" +"Lorsqu'aucune interface est sélectionnée, l'interface maître MPTCP est " +"utilisée (ou une autre interface si le maître est arrêté)." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +msgid "When none selected, MPTCP master interface is used." +msgstr "" +"Lorsqu'aucune interface est sélectionnée, l'interface maître MPTCP est " +"utilisée." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 msgid "port" msgstr "port" +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 +msgid "protocol" +msgstr "protocole" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 +msgid "source MAC-Address" +msgstr "Adresse MAC source" + +#~ msgid "MAC-Address" +#~ msgstr "Adresse MAC" + +#~ msgid "ASN" +#~ msgstr "ASN" + +#~ msgid "ALL" +#~ msgstr "TOUT" + +#~ msgid "Bypass" +#~ msgstr "Contourne" + +#~ msgid "Default" +#~ msgstr "Défaut" + +#~ msgid "" +#~ "Here you can bypass ShadowSocks and VPN. If you set Interface to Default " +#~ "this use any working interface." +#~ msgstr "" +#~ "Ici vous pouvez contouner Shadowsocks et le VPN. Si vous mettez " +#~ "l'interface à défaut, ça utilisera n'importe qu'elle interface " +#~ "fonctionnant." + #~ msgid "Add" #~ msgstr "Ajouter" @@ -135,9 +177,6 @@ msgstr "port" #~ msgid "Domains, ips or networks" #~ msgstr "Domaines, IPs et réseaux" -#~ msgid "MAC-Address" -#~ msgstr "Adresse MAC" - #~ msgid "Output interface" #~ msgstr "Interface de sortie" diff --git a/luci-app-omr-bypass/po/it/omr-bypass.po b/luci-app-omr-bypass/po/it/omr-bypass.po index c26d571f3..df50f91d0 100755 --- a/luci-app-omr-bypass/po/it/omr-bypass.po +++ b/luci-app-omr-bypass/po/it/omr-bypass.po @@ -10,12 +10,12 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:153 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 msgid "ASN" msgstr "ASN" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 msgid "Domain" msgstr "Dominio" @@ -23,45 +23,56 @@ msgstr "Dominio" msgid "Domains" msgstr "Domini" +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" +msgstr "" + #: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 msgid "Grant access to ndpi resources" msgstr "Concedi l'accesso alle risorse ndpi" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:47 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 msgid "IP" msgstr "IP" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:130 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 msgid "IP Address" msgstr "Indirizzo IP" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 msgid "IPs and Networks" msgstr "IP e reti" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:73 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:96 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:117 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:156 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:197 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 msgid "Interface" msgstr "Interfaccia" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:104 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 msgid "MAC-Address" msgstr "Indirizzo MAC" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:39 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:55 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:78 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:122 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:161 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:202 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 msgid "Note" msgstr "Nota" @@ -74,49 +85,57 @@ msgstr "OMR-Bypass" msgid "OpenMPTCProuter IP must be used as DNS." msgstr "L'IP di OpenMPTCProuter deve essere utilizzato come DNS." -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:58 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 msgid "Ports destination" msgstr "Destinazione dei porti" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:81 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 msgid "Ports source" msgstr "Origine delle porte" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:169 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 msgid "Protocol/Service" msgstr "Protocollo / servizio" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:164 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 msgid "Protocols and services" msgstr "Protocolli e servizi" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:125 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 msgid "Source lan IP address or network" msgstr "Indirizzo IP lan di origine o rete" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:73 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:96 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:117 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:156 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:197 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +#, fuzzy +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "" +"Quando non è selezionato nessuno, viene utilizzata l'interfaccia master " +"MPTCP." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 msgid "When none selected, MPTCP master interface is used." msgstr "" "Quando non è selezionato nessuno, viene utilizzata l'interfaccia master " "MPTCP." -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:63 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:86 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 msgid "port" msgstr "Porta" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:66 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:89 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 msgid "protocol" msgstr "Protocollo" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:109 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 msgid "source MAC-Address" msgstr "indirizzo MAC di origine" diff --git a/luci-app-omr-bypass/po/it/omr-bypass.po~ b/luci-app-omr-bypass/po/it/omr-bypass.po~ new file mode 100644 index 000000000..c7e10446a --- /dev/null +++ b/luci-app-omr-bypass/po/it/omr-bypass.po~ @@ -0,0 +1,142 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-10-02 08:44+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 +msgid "ASN" +msgstr "ASN" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 +msgid "Domain" +msgstr "Dominio" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:26 +msgid "Domains" +msgstr "Domini" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" +msgstr "" + +#: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 +msgid "Grant access to ndpi resources" +msgstr "Concedi l'accesso alle risorse ndpi" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 +msgid "IP" +msgstr "IP" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 +msgid "IP Address" +msgstr "Indirizzo IP" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 +msgid "IPs and Networks" +msgstr "IP e reti" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "Interface" +msgstr "Interfaccia" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 +msgid "MAC-Address" +msgstr "Indirizzo MAC" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 +msgid "Note" +msgstr "Nota" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +#: luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json:3 +msgid "OMR-Bypass" +msgstr "OMR-Bypass" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +msgid "OpenMPTCProuter IP must be used as DNS." +msgstr "L'IP di OpenMPTCProuter deve essere utilizzato come DNS." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 +msgid "Ports destination" +msgstr "Destinazione dei porti" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 +msgid "Ports source" +msgstr "Origine delle porte" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 +msgid "Protocol/Service" +msgstr "Protocollo / servizio" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 +msgid "Protocols and services" +msgstr "Protocolli e servizi" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 +msgid "Source lan IP address or network" +msgstr "Indirizzo IP lan di origine o rete" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +#, fuzzy +#| msgid "When none selected, MPTCP master interface is used." +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "" +"Quando non è selezionato nessuno, viene utilizzata l'interfaccia master " +"MPTCP." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +msgid "When none selected, MPTCP master interface is used." +msgstr "" +"Quando non è selezionato nessuno, viene utilizzata l'interfaccia master " +"MPTCP." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 +msgid "port" +msgstr "Porta" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 +msgid "protocol" +msgstr "Protocollo" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 +msgid "source MAC-Address" +msgstr "indirizzo MAC di origine" diff --git a/luci-app-omr-bypass/po/oc/omr-bypass.po b/luci-app-omr-bypass/po/oc/omr-bypass.po index f980655c9..d2583d441 100755 --- a/luci-app-omr-bypass/po/oc/omr-bypass.po +++ b/luci-app-omr-bypass/po/oc/omr-bypass.po @@ -10,12 +10,12 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.0.4\n" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:153 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 msgid "ASN" msgstr "ASN" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 msgid "Domain" msgstr "Domeni" @@ -23,45 +23,56 @@ msgstr "Domeni" msgid "Domains" msgstr "Domenis" +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" +msgstr "" + #: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 msgid "Grant access to ndpi resources" msgstr "Acordar l'accès a las ressorsas ndpi" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:47 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 msgid "IP" msgstr "IP" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:130 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 msgid "IP Address" msgstr "Adreça IP" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 msgid "IPs and Networks" msgstr "IPs e rets" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:73 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:96 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:117 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:156 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:197 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 msgid "Interface" msgstr "Interfàcia" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:104 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 msgid "MAC-Address" msgstr "Adreça MAC" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:39 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:55 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:78 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:122 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:161 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:202 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 msgid "Note" msgstr "Nòta" @@ -74,47 +85,53 @@ msgstr "OMR-Bypass" msgid "OpenMPTCProuter IP must be used as DNS." msgstr "L'IP d'OpznMPTCProuter deu èsser coma lo DNS." -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:58 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 msgid "Ports destination" msgstr "Pòrts de destinacion" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:81 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 msgid "Ports source" msgstr "Pòrts fonts" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:169 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 msgid "Protocol/Service" msgstr "Protocòl/Servici" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:164 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 msgid "Protocols and services" msgstr "Protocòls e servicis" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:125 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 msgid "Source lan IP address or network" msgstr "Adreça IP font o rer" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:73 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:96 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:117 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:156 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:197 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +#, fuzzy +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "Quand res es pas seleccionat, l'interfàcia MPTCP màger es utilizada." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 msgid "When none selected, MPTCP master interface is used." msgstr "Quand res es pas seleccionat, l'interfàcia MPTCP màger es utilizada." -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:63 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:86 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 msgid "port" msgstr "pòrt" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:66 -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:89 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 msgid "protocol" msgstr "protocòl" -#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:109 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 msgid "source MAC-Address" msgstr "Adreça MAC font" diff --git a/luci-app-omr-bypass/po/oc/omr-bypass.po~ b/luci-app-omr-bypass/po/oc/omr-bypass.po~ new file mode 100644 index 000000000..27f06969c --- /dev/null +++ b/luci-app-omr-bypass/po/oc/omr-bypass.po~ @@ -0,0 +1,138 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-18 18:16+0000\n" +"Last-Translator: Quentin PAGÈS \n" +"Language-Team: Occitan \n" +"Language: oc\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 +msgid "ASN" +msgstr "ASN" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 +msgid "Domain" +msgstr "Domeni" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:26 +msgid "Domains" +msgstr "Domenis" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" +msgstr "" + +#: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 +msgid "Grant access to ndpi resources" +msgstr "Acordar l'accès a las ressorsas ndpi" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 +msgid "IP" +msgstr "IP" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 +msgid "IP Address" +msgstr "Adreça IP" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 +msgid "IPs and Networks" +msgstr "IPs e rets" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "Interface" +msgstr "Interfàcia" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 +msgid "MAC-Address" +msgstr "Adreça MAC" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 +msgid "Note" +msgstr "Nòta" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +#: luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json:3 +msgid "OMR-Bypass" +msgstr "OMR-Bypass" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +msgid "OpenMPTCProuter IP must be used as DNS." +msgstr "L'IP d'OpznMPTCProuter deu èsser coma lo DNS." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 +msgid "Ports destination" +msgstr "Pòrts de destinacion" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 +msgid "Ports source" +msgstr "Pòrts fonts" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 +msgid "Protocol/Service" +msgstr "Protocòl/Servici" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 +msgid "Protocols and services" +msgstr "Protocòls e servicis" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 +msgid "Source lan IP address or network" +msgstr "Adreça IP font o rer" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +#, fuzzy +#| msgid "When none selected, MPTCP master interface is used." +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "Quand res es pas seleccionat, l'interfàcia MPTCP màger es utilizada." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +msgid "When none selected, MPTCP master interface is used." +msgstr "Quand res es pas seleccionat, l'interfàcia MPTCP màger es utilizada." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 +msgid "port" +msgstr "pòrt" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 +msgid "protocol" +msgstr "protocòl" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 +msgid "source MAC-Address" +msgstr "Adreça MAC font" diff --git a/luci-app-omr-bypass/po/ru/omr-bypass.po b/luci-app-omr-bypass/po/ru/omr-bypass.po new file mode 100644 index 000000000..7b6f43c6f --- /dev/null +++ b/luci-app-omr-bypass/po/ru/omr-bypass.po @@ -0,0 +1,139 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 +msgid "ASN" +msgstr "ASN" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 +msgid "Domain" +msgstr "Домен" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:26 +msgid "Domains" +msgstr "Домены" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" +msgstr "Установлено" + +#: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 +msgid "Grant access to ndpi resources" +msgstr "Полный доступ к ресурсам ndpi" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 +msgid "IP" +msgstr "IP" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 +msgid "IP Address" +msgstr "IP-адрес" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 +msgid "IPs and Networks" +msgstr "IP-адреса и сети" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "Interface" +msgstr "Интерфейс" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 +msgid "MAC-Address" +msgstr "MAC-адрес" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 +msgid "Note" +msgstr "Примечание" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +#: luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json:3 +msgid "OMR-Bypass" +msgstr "OMR байпас" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +msgid "OpenMPTCProuter IP must be used as DNS." +msgstr "IP OpenMPTCProuter должен использоваться в качестве DNS." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 +msgid "Ports destination" +msgstr "Порты назначения" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 +msgid "Ports source" +msgstr "Порты источника" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 +msgid "Protocol/Service" +msgstr "Протокол / Сервис" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 +msgid "Protocols and services" +msgstr "Протоколы и сервисы" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 +msgid "Source lan IP address or network" +msgstr "Исходный IP-адрес LAN или сеть" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "" +"Если ничего не выбрано, используется главный интерфейс MPTCP (или другой " +"интерфейс, если мастер не работает)." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +msgid "When none selected, MPTCP master interface is used." +msgstr "Если ничего не выбрано, используется главный интерфейс MPTCP." + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 +msgid "port" +msgstr "Порт" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 +msgid "protocol" +msgstr "протокол" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 +msgid "source MAC-Address" +msgstr "MAC-адрес источника" diff --git a/luci-app-omr-bypass/po/zh_Hans/omr-bypass.po b/luci-app-omr-bypass/po/zh_Hans/omr-bypass.po index d28ea26d8..66a55bb21 100755 --- a/luci-app-omr-bypass/po/zh_Hans/omr-bypass.po +++ b/luci-app-omr-bypass/po/zh_Hans/omr-bypass.po @@ -1,119 +1,136 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-09-02 05:14+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-05 11:40+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:64 -msgid "MAC-Address" -msgstr "MAC4-地址" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:100 -msgid "ASN" -msgstr "ASN4" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:52 -msgid "ALL" -msgstr "所有" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:105 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:166 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:174 msgid "ASN" msgstr "ASN" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:9 -msgid "Bypass" -msgstr "绕过" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:150 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:151 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:152 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:153 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:154 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:155 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:156 -msgid "Default" -msgstr "默认" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:16 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:34 msgid "Domain" -msgstr "域名" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:11 -msgid "Domains" msgstr "域" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:9 -msgid "" -"Here you can bypass ShadowSocks and VPN. If you set Interface to Default " -"this use any working interface." -msgstr "在这里,您可以绕过ShadowSocks和VPN. 如果将网卡设置为默认则可以使用任何工作网卡." +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:26 +msgid "Domains" +msgstr "域名" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:31 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:50 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:69 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:95 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:121 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:145 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:171 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:190 +msgid "Enabled" +msgstr "启用" + +#: luci-app-omr-bypass/root/usr/share/rpcd/acl.d/luci-app-omr-bypass.json:3 +msgid "Grant access to ndpi resources" +msgstr "授予对ndpi资源的访问权限" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:53 msgid "IP" msgstr "IP" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:90 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:148 msgid "IP Address" msgstr "IP地址" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:26 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:45 msgid "IPs and Networks" msgstr "IP和网络" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:21 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:36 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:59 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:80 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:95 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:109 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 msgid "Interface" msgstr "接口" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:24 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:39 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:62 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:83 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:98 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:112 -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:140 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:116 +msgid "MAC-Address" +msgstr "MAC地址" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:61 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:87 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:113 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:137 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:163 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:182 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:226 msgid "Note" -msgstr "注意" +msgstr "请注意" -#: luci-app-omr-bypass/luasrc/controller/omr-bypass.lua:6 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +#: luci-app-omr-bypass/root/usr/share/luci/menu.d/luci-app-omr-bypass.json:3 msgid "OMR-Bypass" -msgstr "OMR-绕过" +msgstr "绕过聚合路由" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:42 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:24 +msgid "OpenMPTCProuter IP must be used as DNS." +msgstr "OpenMPTCProuter IP必须作为DNS。" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:64 msgid "Ports destination" msgstr "目的端口" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:51 -msgid "Protocol" -msgstr "协议" +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:90 +msgid "Ports source" +msgstr "源端口" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:119 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:193 msgid "Protocol/Service" msgstr "协议/服务" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:114 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:185 msgid "Protocols and services" msgstr "协议和服务" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:69 -msgid "Source MAC-Address" -msgstr "源MAC地址" - -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:85 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:140 msgid "Source lan IP address or network" msgstr "源局域网IP地址或网络" -#: luci-app-omr-bypass/luasrc/model/cbi/omr-bypass.lua:47 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:221 +msgid "" +"When none selected, MPTCP master interface is used (or an other interface if " +"master is down)." +msgstr "当未选中时,使用MPTCP主接口(如果主接口下线,则使用其他接口)。" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:37 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:56 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:82 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:108 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:132 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:158 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:177 +msgid "When none selected, MPTCP master interface is used." +msgstr "当不选中时,使用MPTCP主接口。" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:72 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:98 msgid "port" msgstr "端口" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:75 +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:101 +msgid "protocol" +msgstr "协议" + +#: luci-app-omr-bypass/htdocs/luci-static/resources/view/services/omr-bypass.js:124 +msgid "source MAC-Address" +msgstr "源MAC地址" diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index dd4050da4..692eddf18 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -1,7 +1,7 @@ #!/bin/sh /etc/rc.common # Copyright (C) 2018-2020 Ycarus (Yannick Chabanois) -START=99 +START=98 STOP=10 USE_PROCD=1 EXTRA_COMMANDS="reload_rules bypass_asn" @@ -341,31 +341,33 @@ _bypass_proto() { [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return - if [ "$intf" = "all" ]; then - iptables-restore -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ]; then + if [ "$intf" = "all" ]; then + iptables-restore -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 COMMIT EOF - fi - else - iptables-restore -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - ip6tables-restore -w --wait=60 --noflush <<-EOF + if [ "$disableipv6" = "0" ]; then + ip6tables-restore -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 + COMMIT + EOF + fi + else + iptables-restore -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid COMMIT EOF + if [ "$disableipv6" = "0" ]; then + ip6tables-restore -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid + COMMIT + EOF + fi fi fi # Use dnsmasq ipset to bypass domains of the proto diff --git a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass index 37bbf4ce3..9ced39f93 100755 --- a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass +++ b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass @@ -110,6 +110,14 @@ if [ "$(uci -q get omr-bypass.disneyplus)" = "" ]; then commit omr-bypass EOF fi +if [ "$(uci -q get omr-bypass.amazonvideo)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set omr-bypass.amazonvideo=proto + add_list omr-bypass.amazonvideo.url='cloudfront.net' + add_list omr-bypass.amazonvideo.url='llnw.net' + commit omr-bypass + EOF +fi if [ ! -f /etc/crontabs/root ] || [ "$(cat /etc/crontabs/root | grep bypass)" = "" ]; then echo "0 2 * * * /etc/init.d/omr-bypass bypass_asn" >> /etc/crontabs/root fi diff --git a/luci-app-omr-dscp/po/de/omr-dscp.po b/luci-app-omr-dscp/po/de/omr-dscp.po index 9efa17a88..be6e36aa2 100755 --- a/luci-app-omr-dscp/po/de/omr-dscp.po +++ b/luci-app-omr-dscp/po/de/omr-dscp.po @@ -11,56 +11,59 @@ msgstr "" "X-Generator: Weblate 4.0.4\n" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 msgid "CS0 - Normal/Best Effort" msgstr "CS0 - normal/best effort" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 msgid "CS1 - Low priority" msgstr "CS - Niedrige Priorität" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 msgid "CS2 - High priority" msgstr "CS2 - Hohe Priorität" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 msgid "CS3 - SIP" msgstr "CS3 - SIP/VoIP" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 -msgid "CS4 - Streaming video" -msgstr "CS4 - Video-Streaming" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS4 - Real-Time Interactive" +msgstr "" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS5 - Broadcast Video" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 -msgid "CS5" -msgstr "CS5" +msgid "CS5 - Broadcast video" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 msgid "CS6 - Network routing" msgstr "CS6 - Netzwerk-Transportschicht" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 -msgid "CS7" -msgstr "CS7" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "CS7 - Latency sensitive" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 msgid "Class" msgstr "Klasse" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:16 msgid "Classification Rules" msgstr "Klassifizierungs-Regeln" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:83 msgid "Comment" msgstr "Kommentar" @@ -76,19 +79,19 @@ msgstr "DSCP-Domains" msgid "DSCP by domain" msgstr "DSCP pro Domain" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:58 msgid "Destination host" msgstr "Ziel-Hostsystem" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:64 msgid "Destination ports" msgstr "Ziel-Port" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 msgid "Differentiated services" msgstr "Differenzierte Dienste" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:29 msgid "Direction" msgstr "Richtung" @@ -100,7 +103,7 @@ msgstr "Domain" msgid "Domains" msgstr "Domains" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:81 msgid "EF - Voice" msgstr "EF - Sprachübertragung" @@ -108,11 +111,16 @@ msgstr "EF - Sprachübertragung" msgid "EF Voice" msgstr "EF Sprachübertragung" +#: luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json:3 +msgid "Grant UCI access for luci-app-dscp" +msgstr "" + #: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +#: luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json:3 msgid "OMR-DSCP" msgstr "OMR-DSCP" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:36 msgid "Protocol" msgstr "Protokoll" @@ -120,15 +128,15 @@ msgstr "Protokoll" msgid "Set DSCP by domains." msgstr "DSCP domainspezifizisch einstellen" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:47 msgid "Source host" msgstr "Quell-Hostsystem" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:52 msgid "Source ports" msgstr "Quell-Ports" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:12 msgid "" "Traffic may be classified by many different parameters, such as source " "address, destination address or traffic type and assigned to a specific " @@ -138,21 +146,30 @@ msgstr "" "nach Quell- oder Zieladresse, nach Daten-Typ oder speziell zugeordneter " "Verkehrsklasse." -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:49 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:54 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:60 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:66 msgid "all" msgstr "alle" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:34 msgid "both" msgstr "beide" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 msgid "download" msgstr "Downstream" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 msgid "upload" msgstr "Upstream" + +#~ msgid "CS4 - Streaming video" +#~ msgstr "CS4 - Video-Streaming" + +#~ msgid "CS5" +#~ msgstr "CS5" + +#~ msgid "CS7" +#~ msgstr "CS7" diff --git a/luci-app-omr-dscp/po/de/omr-dscp.po~ b/luci-app-omr-dscp/po/de/omr-dscp.po~ new file mode 100644 index 000000000..9efa17a88 --- /dev/null +++ b/luci-app-omr-dscp/po/de/omr-dscp.po~ @@ -0,0 +1,158 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-14 08:04+0000\n" +"Last-Translator: Andreas Dorfer \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +msgid "CS0 - Normal/Best Effort" +msgstr "CS0 - normal/best effort" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +msgid "CS1 - Low priority" +msgstr "CS - Niedrige Priorität" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +msgid "CS2 - High priority" +msgstr "CS2 - Hohe Priorität" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +msgid "CS3 - SIP" +msgstr "CS3 - SIP/VoIP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 +msgid "CS4 - Streaming video" +msgstr "CS4 - Video-Streaming" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS5" +msgstr "CS5" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS6 - Network routing" +msgstr "CS6 - Netzwerk-Transportschicht" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 +msgid "CS7" +msgstr "CS7" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +msgid "Class" +msgstr "Klasse" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +msgid "Classification Rules" +msgstr "Klassifizierungs-Regeln" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +msgid "Comment" +msgstr "Kommentar" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:6 +msgid "DSCP" +msgstr "DSCP" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:7 +msgid "DSCP Domains" +msgstr "DSCP-Domains" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "DSCP by domain" +msgstr "DSCP pro Domain" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +msgid "Destination host" +msgstr "Ziel-Hostsystem" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +msgid "Destination ports" +msgstr "Ziel-Port" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +msgid "Differentiated services" +msgstr "Differenzierte Dienste" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +msgid "Direction" +msgstr "Richtung" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:15 +msgid "Domain" +msgstr "Domain" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:10 +msgid "Domains" +msgstr "Domains" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "EF - Voice" +msgstr "EF - Sprachübertragung" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:29 +msgid "EF Voice" +msgstr "EF Sprachübertragung" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +msgid "OMR-DSCP" +msgstr "OMR-DSCP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +msgid "Protocol" +msgstr "Protokoll" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "Set DSCP by domains." +msgstr "DSCP domainspezifizisch einstellen" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +msgid "Source host" +msgstr "Quell-Hostsystem" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +msgid "Source ports" +msgstr "Quell-Ports" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +msgid "" +"Traffic may be classified by many different parameters, such as source " +"address, destination address or traffic type and assigned to a specific " +"traffic class." +msgstr "" +"Nutzdaten können nach verschiedenen Kriterien klassifiziert werden. Z.B. " +"nach Quell- oder Zieladresse, nach Daten-Typ oder speziell zugeordneter " +"Verkehrsklasse." + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +msgid "all" +msgstr "alle" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +msgid "both" +msgstr "beide" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +msgid "download" +msgstr "Downstream" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +msgid "upload" +msgstr "Upstream" diff --git a/luci-app-omr-dscp/po/fr/omr-dscp.po b/luci-app-omr-dscp/po/fr/omr-dscp.po index 96fc1bf68..8ab04ac95 100755 --- a/luci-app-omr-dscp/po/fr/omr-dscp.po +++ b/luci-app-omr-dscp/po/fr/omr-dscp.po @@ -14,56 +14,59 @@ msgstr "" "X-Generator: Weblate 4.5.2\n" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 msgid "CS0 - Normal/Best Effort" msgstr "CS0 - Effort normal / optimal" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 msgid "CS1 - Low priority" msgstr "CS1 - Faible priorité" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 msgid "CS2 - High priority" msgstr "CS2 - Haute priorité" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 msgid "CS3 - SIP" msgstr "CS3 - SIP" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 -msgid "CS4 - Streaming video" -msgstr "CS4 - Vidéo en streaming" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS4 - Real-Time Interactive" +msgstr "" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS5 - Broadcast Video" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 -msgid "CS5" -msgstr "CS5" +msgid "CS5 - Broadcast video" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 msgid "CS6 - Network routing" msgstr "CS6 - Routage réseau" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 -msgid "CS7" -msgstr "CS7" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "CS7 - Latency sensitive" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 msgid "Class" msgstr "Classe" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:16 msgid "Classification Rules" msgstr "Règles de classification" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:83 msgid "Comment" msgstr "Commentaire" @@ -79,19 +82,19 @@ msgstr "DSCP Domaines" msgid "DSCP by domain" msgstr "DSCP par domaine" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:58 msgid "Destination host" msgstr "Hôte de destination" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:64 msgid "Destination ports" msgstr "Ports de destination" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 msgid "Differentiated services" msgstr "Services différenciés" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:29 msgid "Direction" msgstr "Direction" @@ -103,7 +106,7 @@ msgstr "Domaine" msgid "Domains" msgstr "Domaines" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:81 msgid "EF - Voice" msgstr "EF - Voix" @@ -111,11 +114,16 @@ msgstr "EF - Voix" msgid "EF Voice" msgstr "EF - Voix" +#: luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json:3 +msgid "Grant UCI access for luci-app-dscp" +msgstr "" + #: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +#: luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json:3 msgid "OMR-DSCP" msgstr "OMR-DSCP" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:36 msgid "Protocol" msgstr "Protocole" @@ -123,15 +131,15 @@ msgstr "Protocole" msgid "Set DSCP by domains." msgstr "Configurer DSCP par domaine" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:47 msgid "Source host" msgstr "Hôte source" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:52 msgid "Source ports" msgstr "Ports source" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:12 msgid "" "Traffic may be classified by many different parameters, such as source " "address, destination address or traffic type and assigned to a specific " @@ -141,21 +149,30 @@ msgstr "" "l'adresse source, l'adresse de destination ou le type de trafic et attribué " "à une classe de trafic spécifique." -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:49 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:54 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:60 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:66 msgid "all" msgstr "Tous" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:34 msgid "both" msgstr "Les deux" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 msgid "download" msgstr "Téléchargement" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 msgid "upload" msgstr "Envoie" + +#~ msgid "CS4 - Streaming video" +#~ msgstr "CS4 - Vidéo en streaming" + +#~ msgid "CS5" +#~ msgstr "CS5" + +#~ msgid "CS7" +#~ msgstr "CS7" diff --git a/luci-app-omr-dscp/po/fr/omr-dscp.po~ b/luci-app-omr-dscp/po/fr/omr-dscp.po~ new file mode 100644 index 000000000..96fc1bf68 --- /dev/null +++ b/luci-app-omr-dscp/po/fr/omr-dscp.po~ @@ -0,0 +1,161 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +msgid "CS0 - Normal/Best Effort" +msgstr "CS0 - Effort normal / optimal" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +msgid "CS1 - Low priority" +msgstr "CS1 - Faible priorité" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +msgid "CS2 - High priority" +msgstr "CS2 - Haute priorité" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +msgid "CS3 - SIP" +msgstr "CS3 - SIP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 +msgid "CS4 - Streaming video" +msgstr "CS4 - Vidéo en streaming" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS5" +msgstr "CS5" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS6 - Network routing" +msgstr "CS6 - Routage réseau" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 +msgid "CS7" +msgstr "CS7" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +msgid "Class" +msgstr "Classe" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +msgid "Classification Rules" +msgstr "Règles de classification" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +msgid "Comment" +msgstr "Commentaire" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:6 +msgid "DSCP" +msgstr "DSCP" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:7 +msgid "DSCP Domains" +msgstr "DSCP Domaines" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "DSCP by domain" +msgstr "DSCP par domaine" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +msgid "Destination host" +msgstr "Hôte de destination" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +msgid "Destination ports" +msgstr "Ports de destination" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +msgid "Differentiated services" +msgstr "Services différenciés" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +msgid "Direction" +msgstr "Direction" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:15 +msgid "Domain" +msgstr "Domaine" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:10 +msgid "Domains" +msgstr "Domaines" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "EF - Voice" +msgstr "EF - Voix" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:29 +msgid "EF Voice" +msgstr "EF - Voix" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +msgid "OMR-DSCP" +msgstr "OMR-DSCP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +msgid "Protocol" +msgstr "Protocole" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "Set DSCP by domains." +msgstr "Configurer DSCP par domaine" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +msgid "Source host" +msgstr "Hôte source" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +msgid "Source ports" +msgstr "Ports source" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +msgid "" +"Traffic may be classified by many different parameters, such as source " +"address, destination address or traffic type and assigned to a specific " +"traffic class." +msgstr "" +"Le trafic peut être classé selon de nombreux paramètres différents, tels que " +"l'adresse source, l'adresse de destination ou le type de trafic et attribué " +"à une classe de trafic spécifique." + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +msgid "all" +msgstr "Tous" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +msgid "both" +msgstr "Les deux" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +msgid "download" +msgstr "Téléchargement" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +msgid "upload" +msgstr "Envoie" diff --git a/luci-app-omr-dscp/po/it/omr-dscp.po b/luci-app-omr-dscp/po/it/omr-dscp.po index f6a098de2..6194b0c41 100755 --- a/luci-app-omr-dscp/po/it/omr-dscp.po +++ b/luci-app-omr-dscp/po/it/omr-dscp.po @@ -11,56 +11,59 @@ msgstr "" "X-Generator: Weblate 4.0.4\n" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 msgid "CS0 - Normal/Best Effort" msgstr "CS0 - Normale / Miglior sforzo" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 msgid "CS1 - Low priority" msgstr "CS1 - Priorità bassa" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 msgid "CS2 - High priority" msgstr "CS2 - Alta priorità" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 msgid "CS3 - SIP" msgstr "CS3 - SIP" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 -msgid "CS4 - Streaming video" -msgstr "CS4 - Streaming video" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS4 - Real-Time Interactive" +msgstr "" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS5 - Broadcast Video" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 -msgid "CS5" -msgstr "CS5" +msgid "CS5 - Broadcast video" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 msgid "CS6 - Network routing" msgstr "CS6 - Routing di rete" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 -msgid "CS7" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "CS7 - Latency sensitive" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 msgid "Class" msgstr "Classe" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:16 msgid "Classification Rules" msgstr "Regole di classificazione" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:83 msgid "Comment" msgstr "Commenti" @@ -76,19 +79,19 @@ msgstr "Domini DSCP" msgid "DSCP by domain" msgstr "DSCP per dominio" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:58 msgid "Destination host" msgstr "Host di destinazione" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:64 msgid "Destination ports" msgstr "Porte di destinazione" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 msgid "Differentiated services" msgstr "Servizi differenziati" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:29 msgid "Direction" msgstr "" @@ -100,7 +103,7 @@ msgstr "Dominio" msgid "Domains" msgstr "Domini" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:81 msgid "EF - Voice" msgstr "EF - Voce" @@ -108,11 +111,16 @@ msgstr "EF - Voce" msgid "EF Voice" msgstr "EF - Voce" +#: luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json:3 +msgid "Grant UCI access for luci-app-dscp" +msgstr "" + #: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +#: luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json:3 msgid "OMR-DSCP" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:36 msgid "Protocol" msgstr "Protocollo" @@ -120,15 +128,15 @@ msgstr "Protocollo" msgid "Set DSCP by domains." msgstr "Imposta DSCP per domini." -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:47 msgid "Source host" msgstr "Host di origine" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:52 msgid "Source ports" msgstr "Porte di origine" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:12 msgid "" "Traffic may be classified by many different parameters, such as source " "address, destination address or traffic type and assigned to a specific " @@ -138,21 +146,27 @@ msgstr "" "indirizzo di origine, indirizzo di destinazione o tipo di traffico e " "assegnato a una classe di traffico specifica." -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:49 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:54 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:60 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:66 msgid "all" msgstr "tutti" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:34 msgid "both" msgstr "entrambi" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 msgid "download" msgstr "Scarica" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 msgid "upload" msgstr "Carica" + +#~ msgid "CS4 - Streaming video" +#~ msgstr "CS4 - Streaming video" + +#~ msgid "CS5" +#~ msgstr "CS5" diff --git a/luci-app-omr-dscp/po/it/omr-dscp.po~ b/luci-app-omr-dscp/po/it/omr-dscp.po~ new file mode 100644 index 000000000..f6a098de2 --- /dev/null +++ b/luci-app-omr-dscp/po/it/omr-dscp.po~ @@ -0,0 +1,158 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-09-21 12:51+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +msgid "CS0 - Normal/Best Effort" +msgstr "CS0 - Normale / Miglior sforzo" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +msgid "CS1 - Low priority" +msgstr "CS1 - Priorità bassa" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +msgid "CS2 - High priority" +msgstr "CS2 - Alta priorità" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +msgid "CS3 - SIP" +msgstr "CS3 - SIP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 +msgid "CS4 - Streaming video" +msgstr "CS4 - Streaming video" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS5" +msgstr "CS5" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS6 - Network routing" +msgstr "CS6 - Routing di rete" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 +msgid "CS7" +msgstr "" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +msgid "Class" +msgstr "Classe" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +msgid "Classification Rules" +msgstr "Regole di classificazione" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +msgid "Comment" +msgstr "Commenti" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:6 +msgid "DSCP" +msgstr "" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:7 +msgid "DSCP Domains" +msgstr "Domini DSCP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "DSCP by domain" +msgstr "DSCP per dominio" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +msgid "Destination host" +msgstr "Host di destinazione" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +msgid "Destination ports" +msgstr "Porte di destinazione" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +msgid "Differentiated services" +msgstr "Servizi differenziati" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +msgid "Direction" +msgstr "" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:15 +msgid "Domain" +msgstr "Dominio" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:10 +msgid "Domains" +msgstr "Domini" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "EF - Voice" +msgstr "EF - Voce" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:29 +msgid "EF Voice" +msgstr "EF - Voce" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +msgid "OMR-DSCP" +msgstr "" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +msgid "Protocol" +msgstr "Protocollo" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "Set DSCP by domains." +msgstr "Imposta DSCP per domini." + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +msgid "Source host" +msgstr "Host di origine" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +msgid "Source ports" +msgstr "Porte di origine" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +msgid "" +"Traffic may be classified by many different parameters, such as source " +"address, destination address or traffic type and assigned to a specific " +"traffic class." +msgstr "" +"Il traffico può essere classificato in base a molti parametri diversi, come " +"indirizzo di origine, indirizzo di destinazione o tipo di traffico e " +"assegnato a una classe di traffico specifica." + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +msgid "all" +msgstr "tutti" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +msgid "both" +msgstr "entrambi" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +msgid "download" +msgstr "Scarica" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +msgid "upload" +msgstr "Carica" diff --git a/luci-app-omr-dscp/po/oc/omr-dscp.po b/luci-app-omr-dscp/po/oc/omr-dscp.po index afa7ea69d..c585dd98a 100755 --- a/luci-app-omr-dscp/po/oc/omr-dscp.po +++ b/luci-app-omr-dscp/po/oc/omr-dscp.po @@ -11,56 +11,59 @@ msgstr "" "X-Generator: Weblate 4.0.4\n" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 msgid "CS0 - Normal/Best Effort" msgstr "CS0 - Esfòrç normal / optimal" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 msgid "CS1 - Low priority" msgstr "CS1 - Prioritat febla" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 msgid "CS2 - High priority" msgstr "CS2 - Prioritat nauta" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 msgid "CS3 - SIP" msgstr "CS3 - SIP" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 -msgid "CS4 - Streaming video" -msgstr "CS4 - Difusion vidèo" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS4 - Real-Time Interactive" +msgstr "" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS5 - Broadcast Video" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 -msgid "CS5" -msgstr "CS5" +msgid "CS5 - Broadcast video" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 msgid "CS6 - Network routing" msgstr "CS6 - Partiment ret" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 -msgid "CS7" -msgstr "CS7" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "CS7 - Latency sensitive" +msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 msgid "Class" msgstr "Classa" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:16 msgid "Classification Rules" msgstr "Règlas de classificacion" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:83 msgid "Comment" msgstr "Comentari" @@ -76,19 +79,19 @@ msgstr "DSCP Domenis" msgid "DSCP by domain" msgstr "DSCP per domeni" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:58 msgid "Destination host" msgstr "Òste de destinacion" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:64 msgid "Destination ports" msgstr "Pòrts de destinacion" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 msgid "Differentiated services" msgstr "Servicis diferenciats" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:29 msgid "Direction" msgstr "Direccion" @@ -100,7 +103,7 @@ msgstr "Domeni" msgid "Domains" msgstr "Domenis" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:81 msgid "EF - Voice" msgstr "EF - Votz" @@ -108,11 +111,16 @@ msgstr "EF - Votz" msgid "EF Voice" msgstr "EF - Votz" +#: luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json:3 +msgid "Grant UCI access for luci-app-dscp" +msgstr "" + #: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +#: luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json:3 msgid "OMR-DSCP" msgstr "OMR-DSCP" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:36 msgid "Protocol" msgstr "Protocòl" @@ -120,39 +128,48 @@ msgstr "Protocòl" msgid "Set DSCP by domains." msgstr "Configurar DSCP per domeni." -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:47 msgid "Source host" msgstr "Òste font" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:52 msgid "Source ports" msgstr "Pòrts fonts" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:12 msgid "" "Traffic may be classified by many different parameters, such as source " "address, destination address or traffic type and assigned to a specific " "traffic class." msgstr "" -"Lo trafic pòt èsser classat segon mantuns paramètres diferents, coma l’" -"adreça font, l’adreça de destinacion o lo tipe de trafic e atribuit a una " +"Lo trafic pòt èsser classat segon mantuns paramètres diferents, coma " +"l’adreça font, l’adreça de destinacion o lo tipe de trafic e atribuit a una " "classa de trafic especifica." -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:49 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:54 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:60 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:66 msgid "all" msgstr "totes" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:34 msgid "both" msgstr "Los dos" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 msgid "download" msgstr "Telecargament" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 msgid "upload" msgstr "Mandadís" + +#~ msgid "CS4 - Streaming video" +#~ msgstr "CS4 - Difusion vidèo" + +#~ msgid "CS5" +#~ msgstr "CS5" + +#~ msgid "CS7" +#~ msgstr "CS7" diff --git a/luci-app-omr-dscp/po/oc/omr-dscp.po~ b/luci-app-omr-dscp/po/oc/omr-dscp.po~ new file mode 100644 index 000000000..ed3a33083 --- /dev/null +++ b/luci-app-omr-dscp/po/oc/omr-dscp.po~ @@ -0,0 +1,158 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-31 17:15+0000\n" +"Last-Translator: Quentin PAGÈS \n" +"Language-Team: Occitan \n" +"Language: oc\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +msgid "CS0 - Normal/Best Effort" +msgstr "CS0 - Esfòrç normal / optimal" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +msgid "CS1 - Low priority" +msgstr "CS1 - Prioritat febla" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +msgid "CS2 - High priority" +msgstr "CS2 - Prioritat nauta" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +msgid "CS3 - SIP" +msgstr "CS3 - SIP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 +msgid "CS4 - Streaming video" +msgstr "CS4 - Difusion vidèo" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS5" +msgstr "CS5" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS6 - Network routing" +msgstr "CS6 - Partiment ret" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 +msgid "CS7" +msgstr "CS7" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +msgid "Class" +msgstr "Classa" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +msgid "Classification Rules" +msgstr "Règlas de classificacion" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +msgid "Comment" +msgstr "Comentari" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:6 +msgid "DSCP" +msgstr "DSCP" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:7 +msgid "DSCP Domains" +msgstr "DSCP Domenis" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "DSCP by domain" +msgstr "DSCP per domeni" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +msgid "Destination host" +msgstr "Òste de destinacion" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +msgid "Destination ports" +msgstr "Pòrts de destinacion" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +msgid "Differentiated services" +msgstr "Servicis diferenciats" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +msgid "Direction" +msgstr "Direccion" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:15 +msgid "Domain" +msgstr "Domeni" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:10 +msgid "Domains" +msgstr "Domenis" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "EF - Voice" +msgstr "EF - Votz" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:29 +msgid "EF Voice" +msgstr "EF - Votz" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +msgid "OMR-DSCP" +msgstr "OMR-DSCP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +msgid "Protocol" +msgstr "Protocòl" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "Set DSCP by domains." +msgstr "Configurar DSCP per domeni." + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +msgid "Source host" +msgstr "Òste font" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +msgid "Source ports" +msgstr "Pòrts fonts" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +msgid "" +"Traffic may be classified by many different parameters, such as source " +"address, destination address or traffic type and assigned to a specific " +"traffic class." +msgstr "" +"Lo trafic pòt èsser classat segon mantuns paramètres diferents, coma " +"l’adreça font, l’adreça de destinacion o lo tipe de trafic e atribuit a una " +"classa de trafic especifica." + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +msgid "all" +msgstr "totes" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +msgid "both" +msgstr "Los dos" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +msgid "download" +msgstr "Telecargament" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +msgid "upload" +msgstr "Mandadís" diff --git a/luci-app-omr-dscp/po/templates/omr-dscp.pot b/luci-app-omr-dscp/po/templates/omr-dscp.pot index 91981b0ab..cc022398e 100755 --- a/luci-app-omr-dscp/po/templates/omr-dscp.pot +++ b/luci-app-omr-dscp/po/templates/omr-dscp.pot @@ -2,56 +2,59 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 msgid "CS0 - Normal/Best Effort" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 msgid "CS1 - Low priority" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 msgid "CS2 - High priority" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 msgid "CS3 - SIP" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 -msgid "CS4 - Streaming video" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS4 - Real-Time Interactive" +msgstr "" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS5 - Broadcast Video" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 -msgid "CS5" +msgid "CS5 - Broadcast video" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 msgid "CS6 - Network routing" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 -msgid "CS7" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "CS7 - Latency sensitive" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 msgid "Class" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:16 msgid "Classification Rules" msgstr "" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:83 msgid "Comment" msgstr "" @@ -67,19 +70,19 @@ msgstr "" msgid "DSCP by domain" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:58 msgid "Destination host" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:64 msgid "Destination ports" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 msgid "Differentiated services" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:29 msgid "Direction" msgstr "" @@ -91,7 +94,7 @@ msgstr "" msgid "Domains" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:81 msgid "EF - Voice" msgstr "" @@ -99,11 +102,16 @@ msgstr "" msgid "EF Voice" msgstr "" +#: luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json:3 +msgid "Grant UCI access for luci-app-dscp" +msgstr "" + #: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +#: luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json:3 msgid "OMR-DSCP" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:36 msgid "Protocol" msgstr "" @@ -111,36 +119,36 @@ msgstr "" msgid "Set DSCP by domains." msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:47 msgid "Source host" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:52 msgid "Source ports" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:12 msgid "" "Traffic may be classified by many different parameters, such as source " "address, destination address or traffic type and assigned to a specific " "traffic class." msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:49 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:54 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:60 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:66 msgid "all" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:34 msgid "both" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 msgid "download" msgstr "" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 msgid "upload" msgstr "" diff --git a/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po b/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po index 8c62da0ca..cecea8c87 100755 --- a/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po +++ b/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po @@ -1,66 +1,69 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-06-11 16:36+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-13 21:38+0000\n" +"Last-Translator: justbin <419989953@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 msgid "CS0 - Normal/Best Effort" msgstr "CS0 - 正常/尽量" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 msgid "CS1 - Low priority" msgstr "CS1 - 低优先级" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 msgid "CS2 - High priority" msgstr "CS2 - 高优先级" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 msgid "CS3 - SIP" msgstr "CS3 - SIP" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 -msgid "CS4 - Streaming video" -msgstr "CS4 - 视频流" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS4 - Real-Time Interactive" +msgstr "CS4 - 实时交互" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS5 - Broadcast Video" +msgstr "CS5 - 视频广播" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 -msgid "CS5" -msgstr "CS5" +msgid "CS5 - Broadcast video" +msgstr "CS5 - 视频广播" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 msgid "CS6 - Network routing" msgstr "CS6-网络路由" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 -msgid "CS7" -msgstr "CS7" +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "CS7 - Latency sensitive" +msgstr "CS7 - 时延敏感" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 msgid "Class" msgstr "类" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:16 msgid "Classification Rules" msgstr "分类规则" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:83 msgid "Comment" msgstr "注释" @@ -76,31 +79,31 @@ msgstr "DSCP域" msgid "DSCP by domain" msgstr "DSCP按域名" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:58 msgid "Destination host" msgstr "目标主机" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:64 msgid "Destination ports" msgstr "目的端口" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 msgid "Differentiated services" msgstr "差异化服务" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:29 msgid "Direction" msgstr "目的" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:15 msgid "Domain" -msgstr "域名" +msgstr "域" #: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:10 msgid "Domains" -msgstr "域" +msgstr "域名" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:81 msgid "EF - Voice" msgstr "EF-语音" @@ -108,11 +111,16 @@ msgstr "EF-语音" msgid "EF Voice" msgstr "EF 语音" +#: luci-app-omr-dscp/root/usr/share/rpcd/acl.d/luci-app-omr-dscp.json:3 +msgid "Grant UCI access for luci-app-dscp" +msgstr "授予luci-app-dscp UCI访问权限" + #: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +#: luci-app-omr-dscp/root/usr/share/luci/menu.d/luci-app-omr-dscp.json:3 msgid "OMR-DSCP" msgstr "OMR-DSCP" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:36 msgid "Protocol" msgstr "协议" @@ -120,36 +128,47 @@ msgstr "协议" msgid "Set DSCP by domains." msgstr "按域设置DSCP." -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:47 msgid "Source host" msgstr "源主机" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:52 msgid "Source ports" msgstr "源端口" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:12 msgid "" "Traffic may be classified by many different parameters, such as source " "address, destination address or traffic type and assigned to a specific " "traffic class." -msgstr "可以通过许多不同的参数(例如源地址,目标地址或流量类型)对流量进行分类,并将其分配给特定的流量类别." +msgstr "" +"可以通过许多不同的参数(例如源地址,目标地址或流量类型)对流量进行分类,并将" +"其分配给特定的流量类别." -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:49 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:54 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:60 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:66 msgid "all" msgstr "所有" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:34 msgid "both" msgstr "都" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 msgid "download" msgstr "下载" -#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 msgid "upload" msgstr "上传" + +#~ msgid "CS4 - Streaming video" +#~ msgstr "CS4 - 视频流" + +#~ msgid "CS5" +#~ msgstr "CS5" + +#~ msgid "CS7" +#~ msgstr "CS7" diff --git a/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po~ b/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po~ new file mode 100644 index 000000000..0a2da9832 --- /dev/null +++ b/luci-app-omr-dscp/po/zh_Hans/omr-dscp.po~ @@ -0,0 +1,157 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-06-11 16:36+0000\n" +"Last-Translator: antrouter \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:21 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:72 +msgid "CS0 - Normal/Best Effort" +msgstr "CS0 - 正常/尽量" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:22 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:73 +msgid "CS1 - Low priority" +msgstr "CS1 - 低优先级" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:23 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:74 +msgid "CS2 - High priority" +msgstr "CS2 - 高优先级" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:24 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:75 +msgid "CS3 - SIP" +msgstr "CS3 - SIP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:25 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:76 +msgid "CS4 - Streaming video" +msgstr "CS4 - 视频流" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:26 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:77 +msgid "CS5" +msgstr "CS5" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:27 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:78 +msgid "CS6 - Network routing" +msgstr "CS6-网络路由" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:28 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:79 +msgid "CS7" +msgstr "CS7" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:20 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:71 +msgid "Class" +msgstr "类" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:15 +msgid "Classification Rules" +msgstr "分类规则" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:31 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:82 +msgid "Comment" +msgstr "注释" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:6 +msgid "DSCP" +msgstr "DSCP" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:7 +msgid "DSCP Domains" +msgstr "DSCP域" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "DSCP by domain" +msgstr "DSCP按域名" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:57 +msgid "Destination host" +msgstr "目标主机" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:63 +msgid "Destination ports" +msgstr "目的端口" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:10 +msgid "Differentiated services" +msgstr "差异化服务" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:28 +msgid "Direction" +msgstr "目的" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:15 +msgid "Domain" +msgstr "域名" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:10 +msgid "Domains" +msgstr "域" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:80 +msgid "EF - Voice" +msgstr "EF-语音" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:29 +msgid "EF Voice" +msgstr "EF 语音" + +#: luci-app-omr-dscp/luasrc/controller/omr-dscp.lua:4 +msgid "OMR-DSCP" +msgstr "OMR-DSCP" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:35 +msgid "Protocol" +msgstr "协议" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp-domains.lua:8 +msgid "Set DSCP by domains." +msgstr "按域设置DSCP." + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:46 +msgid "Source host" +msgstr "源主机" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:51 +msgid "Source ports" +msgstr "源端口" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:11 +msgid "" +"Traffic may be classified by many different parameters, such as source " +"address, destination address or traffic type and assigned to a specific " +"traffic class." +msgstr "" +"可以通过许多不同的参数(例如源地址,目标地址或流量类型)对流量进行分类,并将" +"其分配给特定的流量类别." + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:48 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:53 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:59 +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:65 +msgid "all" +msgstr "所有" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:33 +msgid "both" +msgstr "都" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:32 +msgid "download" +msgstr "下载" + +#: luci-app-omr-dscp/luasrc/model/cbi/dscp.lua:31 +msgid "upload" +msgstr "上传" diff --git a/luci-app-omr-dscp/root/etc/config/dscp b/luci-app-omr-dscp/root/etc/config/dscp index cf300451f..ef2ef31f2 100755 --- a/luci-app-omr-dscp/root/etc/config/dscp +++ b/luci-app-omr-dscp/root/etc/config/dscp @@ -22,20 +22,20 @@ config classify option direction 'both' option proto 'tcp' option class 'cs4' - option src_port '65500' + option dest_port '65500' option comment 'OMR API' config classify option direction 'both' option proto 'tcp' - option class 'cs6' + option class 'cs7' option dest_port '65001,65301,65401,65011' option comment 'OMR vpn' config classify option direction 'both' option proto 'udp' - option class 'cs6' + option class 'cs7' option dest_port '65001,65301' option comment 'OMR vpn' @@ -144,12 +144,17 @@ config domains config domains option name 'whatsapp.net' option class 'cs2' - option comment 'cdn' + option comment 'chat' config domains option name 'whatsapp.com' option class 'cs2' - option comment 'cdn' + option comment 'chat' + +config domains + option name 'zoom.us' + option class 'cs2' + option comment 'chat' config domains option name 'googleapis.com' diff --git a/luci-app-omr-quota/po/de/omr-quota.po b/luci-app-omr-quota/po/de/omr-quota.po index 0c553322d..842f61f5e 100755 --- a/luci-app-omr-quota/po/de/omr-quota.po +++ b/luci-app-omr-quota/po/de/omr-quota.po @@ -18,6 +18,10 @@ msgstr "Hinzufügen" msgid "Enable" msgstr "Aktivieren" +#: luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json:3 +msgid "Grant UCI access for luci-app-omr-quota" +msgstr "" + #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 msgid "Interfaces" msgstr "Anschlüsse" @@ -35,6 +39,7 @@ msgid "Monthly Quota" msgstr "Monatliches Maximalvolumen" #: luci-app-omr-quota/luasrc/controller/quota.lua:11 +#: luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json:3 msgid "Quota" msgstr "Quota" diff --git a/luci-app-omr-quota/po/de/omr-quota.po~ b/luci-app-omr-quota/po/de/omr-quota.po~ new file mode 100644 index 000000000..0c553322d --- /dev/null +++ b/luci-app-omr-quota/po/de/omr-quota.po~ @@ -0,0 +1,57 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-10-05 12:39+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 +msgid "Add" +msgstr "Hinzufügen" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:21 +msgid "Enable" +msgstr "Aktivieren" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 +msgid "Interfaces" +msgstr "Anschlüsse" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:33 +msgid "Interval between check (s)" +msgstr "Abstand zwischen den Überfprüfungen (in Sekunden)" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "Ungültig" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Monthly Quota" +msgstr "Monatliches Maximalvolumen" + +#: luci-app-omr-quota/luasrc/controller/quota.lua:11 +msgid "Quota" +msgstr "Quota" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:27 +msgid "RX quota (kbit)" +msgstr "Empfangsvolumen-Grenze (in kBytes)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Set monthly quota, when quota is reached interface state is set to down" +msgstr "" +"Das monatliche maximale Übertragungsvolumen bei dessen Erreichen der " +"Anschluss nicht weiter genutzt wird." + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:24 +msgid "TX quota (kbit)" +msgstr "Sendevolumen-Grenze (in kBytes)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:30 +msgid "TX+RX quota (kbit)" +msgstr "Gesamtvolumen-Grenze (Rx+Tx in kBytes)" diff --git a/luci-app-omr-quota/po/fr/omr-quota.po b/luci-app-omr-quota/po/fr/omr-quota.po index 10983e45b..a7af2a13a 100755 --- a/luci-app-omr-quota/po/fr/omr-quota.po +++ b/luci-app-omr-quota/po/fr/omr-quota.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -21,6 +21,10 @@ msgstr "Ajouter" msgid "Enable" msgstr "Activer" +#: luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json:3 +msgid "Grant UCI access for luci-app-omr-quota" +msgstr "" + #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 msgid "Interfaces" msgstr "Interfaces" @@ -38,6 +42,7 @@ msgid "Monthly Quota" msgstr "Quota mensuel" #: luci-app-omr-quota/luasrc/controller/quota.lua:11 +#: luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json:3 msgid "Quota" msgstr "Quota" @@ -47,7 +52,9 @@ msgstr "Quota de réception (RX en kbit)" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 msgid "Set monthly quota, when quota is reached interface state is set to down" -msgstr "Configurer le quota mensuel, quand le quota est atteint l'interface est désactivée" +msgstr "" +"Configurer le quota mensuel, quand le quota est atteint l'interface est " +"désactivée" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:24 msgid "TX quota (kbit)" @@ -58,4 +65,5 @@ msgid "TX+RX quota (kbit)" msgstr "Quota de transmission+réception (TX+RX en kbit)" #~ msgid "Set quota, when quota is reached interface state is set to down" -#~ msgstr "Configurer le quota, quand le quota est atteint l'interface est désactivée" +#~ msgstr "" +#~ "Configurer le quota, quand le quota est atteint l'interface est désactivée" diff --git a/luci-app-omr-quota/po/fr/omr-quota.po~ b/luci-app-omr-quota/po/fr/omr-quota.po~ new file mode 100644 index 000000000..d61b27717 --- /dev/null +++ b/luci-app-omr-quota/po/fr/omr-quota.po~ @@ -0,0 +1,64 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 +msgid "Add" +msgstr "Ajouter" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:21 +msgid "Enable" +msgstr "Activer" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 +msgid "Interfaces" +msgstr "Interfaces" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:33 +msgid "Interval between check (s)" +msgstr "Intervalle entre les essais (s)" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "Invalide" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Monthly Quota" +msgstr "Quota mensuel" + +#: luci-app-omr-quota/luasrc/controller/quota.lua:11 +msgid "Quota" +msgstr "Quota" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:27 +msgid "RX quota (kbit)" +msgstr "Quota de réception (RX en kbit)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Set monthly quota, when quota is reached interface state is set to down" +msgstr "" +"Configurer le quota mensuel, quand le quota est atteint l'interface est " +"désactivée" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:24 +msgid "TX quota (kbit)" +msgstr "Quota de transmission (TX en kbit)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:30 +msgid "TX+RX quota (kbit)" +msgstr "Quota de transmission+réception (TX+RX en kbit)" + +#~ msgid "Set quota, when quota is reached interface state is set to down" +#~ msgstr "" +#~ "Configurer le quota, quand le quota est atteint l'interface est désactivée" diff --git a/luci-app-omr-quota/po/it/omr-quota.po b/luci-app-omr-quota/po/it/omr-quota.po index 41412af9e..37e2dfec4 100755 --- a/luci-app-omr-quota/po/it/omr-quota.po +++ b/luci-app-omr-quota/po/it/omr-quota.po @@ -18,6 +18,10 @@ msgstr "Aggiungi" msgid "Enable" msgstr "Attivare" +#: luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json:3 +msgid "Grant UCI access for luci-app-omr-quota" +msgstr "" + #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 msgid "Interfaces" msgstr "Interfaccia" @@ -35,6 +39,7 @@ msgid "Monthly Quota" msgstr "Quota mensile" #: luci-app-omr-quota/luasrc/controller/quota.lua:11 +#: luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json:3 msgid "Quota" msgstr "" diff --git a/luci-app-omr-quota/po/it/omr-quota.po~ b/luci-app-omr-quota/po/it/omr-quota.po~ new file mode 100644 index 000000000..41412af9e --- /dev/null +++ b/luci-app-omr-quota/po/it/omr-quota.po~ @@ -0,0 +1,57 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-09-21 12:51+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 +msgid "Add" +msgstr "Aggiungi" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:21 +msgid "Enable" +msgstr "Attivare" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 +msgid "Interfaces" +msgstr "Interfaccia" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:33 +msgid "Interval between check (s)" +msgstr "Intervallo tra i controlli (s)" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "Non valido" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Monthly Quota" +msgstr "Quota mensile" + +#: luci-app-omr-quota/luasrc/controller/quota.lua:11 +msgid "Quota" +msgstr "" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:27 +msgid "RX quota (kbit)" +msgstr "" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Set monthly quota, when quota is reached interface state is set to down" +msgstr "" +"Imposta la quota mensile, quando viene raggiunta la quota, lo stato " +"dell'interfaccia è impostato su inattivo" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:24 +msgid "TX quota (kbit)" +msgstr "" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:30 +msgid "TX+RX quota (kbit)" +msgstr "" diff --git a/luci-app-omr-quota/po/oc/omr-quota.po b/luci-app-omr-quota/po/oc/omr-quota.po index 87f906d16..dc0cc96e4 100755 --- a/luci-app-omr-quota/po/oc/omr-quota.po +++ b/luci-app-omr-quota/po/oc/omr-quota.po @@ -18,6 +18,10 @@ msgstr "Ajustar" msgid "Enable" msgstr "Activat" +#: luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json:3 +msgid "Grant UCI access for luci-app-omr-quota" +msgstr "" + #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 msgid "Interfaces" msgstr "Interfàcias" @@ -35,6 +39,7 @@ msgid "Monthly Quota" msgstr "Quòta mesadièra" #: luci-app-omr-quota/luasrc/controller/quota.lua:11 +#: luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json:3 msgid "Quota" msgstr "Quòta" diff --git a/luci-app-omr-quota/po/oc/omr-quota.po~ b/luci-app-omr-quota/po/oc/omr-quota.po~ new file mode 100644 index 000000000..87f906d16 --- /dev/null +++ b/luci-app-omr-quota/po/oc/omr-quota.po~ @@ -0,0 +1,56 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-21 20:21+0000\n" +"Last-Translator: Quentin PAGÈS \n" +"Language-Team: Occitan \n" +"Language: oc\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 +msgid "Add" +msgstr "Ajustar" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:21 +msgid "Enable" +msgstr "Activat" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 +msgid "Interfaces" +msgstr "Interfàcias" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:33 +msgid "Interval between check (s)" +msgstr "Interval entre las verificacions (s)" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "Invalid" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Monthly Quota" +msgstr "Quòta mesadièra" + +#: luci-app-omr-quota/luasrc/controller/quota.lua:11 +msgid "Quota" +msgstr "Quòta" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:27 +msgid "RX quota (kbit)" +msgstr "RX quòta (kbit)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Set monthly quota, when quota is reached interface state is set to down" +msgstr "" +"Definir la quòta mesadièra, quand es atenguda l'interfàcia es desactivada" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:24 +msgid "TX quota (kbit)" +msgstr "TX quòta (kbit)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:30 +msgid "TX+RX quota (kbit)" +msgstr "TX+RX quòta (kbit)" diff --git a/luci-app-omr-quota/po/ru/omr-quota.po b/luci-app-omr-quota/po/ru/omr-quota.po new file mode 100644 index 000000000..2d9591607 --- /dev/null +++ b/luci-app-omr-quota/po/ru/omr-quota.po @@ -0,0 +1,62 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 +msgid "Add" +msgstr "Добавить" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:21 +msgid "Enable" +msgstr "Включено" + +#: luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json:3 +msgid "Grant UCI access for luci-app-omr-quota" +msgstr "Разрешить доступ к UCI для luci-app-omr-quota" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 +msgid "Interfaces" +msgstr "Интерфейсы" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:33 +msgid "Interval between check (s)" +msgstr "Интервал между проверками (сек.)" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "Неправильный" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Monthly Quota" +msgstr "Месячная квота" + +#: luci-app-omr-quota/luasrc/controller/quota.lua:11 +#: luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json:3 +msgid "Quota" +msgstr "Квота" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:27 +msgid "RX quota (kbit)" +msgstr "Ограничение на прием (kbit)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Set monthly quota, when quota is reached interface state is set to down" +msgstr "" +"Установить ежемесячную квоту, при достижении квоты интерфейс отключается" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:24 +msgid "TX quota (kbit)" +msgstr "Ограничение на отправку (kbit)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:30 +msgid "TX+RX quota (kbit)" +msgstr "Общее размер квоты (отправка и прием в kbit)" diff --git a/luci-app-omr-quota/po/templates/omr-quota.pot b/luci-app-omr-quota/po/templates/omr-quota.pot index 15235cd19..da48e9212 100755 --- a/luci-app-omr-quota/po/templates/omr-quota.pot +++ b/luci-app-omr-quota/po/templates/omr-quota.pot @@ -9,6 +9,10 @@ msgstr "" msgid "Enable" msgstr "" +#: luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json:3 +msgid "Grant UCI access for luci-app-omr-quota" +msgstr "" + #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 msgid "Interfaces" msgstr "" @@ -26,6 +30,7 @@ msgid "Monthly Quota" msgstr "" #: luci-app-omr-quota/luasrc/controller/quota.lua:11 +#: luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json:3 msgid "Quota" msgstr "" diff --git a/luci-app-omr-quota/po/zh_Hans/omr-quota.po b/luci-app-omr-quota/po/zh_Hans/omr-quota.po index b896c0b3e..f3157f768 100755 --- a/luci-app-omr-quota/po/zh_Hans/omr-quota.po +++ b/luci-app-omr-quota/po/zh_Hans/omr-quota.po @@ -1,14 +1,14 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-06-11 16:36+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-13 21:38+0000\n" +"Last-Translator: justbin <419989953@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" #: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 msgid "Add" @@ -16,11 +16,15 @@ msgstr "添加" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:21 msgid "Enable" -msgstr "开启" +msgstr "启用" + +#: luci-app-omr-quota/root/usr/share/rpcd/acl.d/luci-app-omr-quota.json:3 +msgid "Grant UCI access for luci-app-omr-quota" +msgstr "授予luci-app-omr-quota UCI访问权限" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 msgid "Interfaces" -msgstr "网卡" +msgstr "接口" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:33 msgid "Interval between check (s)" @@ -28,13 +32,14 @@ msgstr "两次检查间隔 (秒)" #: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:9 msgid "Invalid" -msgstr "无效" +msgstr "无效的" #: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 msgid "Monthly Quota" msgstr "每月配额" #: luci-app-omr-quota/luasrc/controller/quota.lua:11 +#: luci-app-omr-quota/root/usr/share/luci/menu.d/luci-app-omr-quota.json:3 msgid "Quota" msgstr "配额" diff --git a/luci-app-omr-quota/po/zh_Hans/omr-quota.po~ b/luci-app-omr-quota/po/zh_Hans/omr-quota.po~ new file mode 100644 index 000000000..b896c0b3e --- /dev/null +++ b/luci-app-omr-quota/po/zh_Hans/omr-quota.po~ @@ -0,0 +1,55 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-06-11 16:36+0000\n" +"Last-Translator: antrouter \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:8 +msgid "Add" +msgstr "添加" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:21 +msgid "Enable" +msgstr "开启" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:10 +msgid "Interfaces" +msgstr "网卡" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:33 +msgid "Interval between check (s)" +msgstr "两次检查间隔 (秒)" + +#: luci-app-omr-quota/luasrc/view/omr-quota/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "无效" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Monthly Quota" +msgstr "每月配额" + +#: luci-app-omr-quota/luasrc/controller/quota.lua:11 +msgid "Quota" +msgstr "配额" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:27 +msgid "RX quota (kbit)" +msgstr "接收配额 (kbit)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:8 +msgid "Set monthly quota, when quota is reached interface state is set to down" +msgstr "设置每月配额,达到配额后将接口状态设置为关闭" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:24 +msgid "TX quota (kbit)" +msgstr "发送配额 (kbit)" + +#: luci-app-omr-quota/luasrc/model/cbi/quota/quota.lua:30 +msgid "TX+RX quota (kbit)" +msgstr "发送+接收配额 (kbit)" diff --git a/luci-app-omr-tracker/po/de/omr-tracker.po b/luci-app-omr-tracker/po/de/omr-tracker.po index 5486fa170..5a60906e0 100755 --- a/luci-app-omr-tracker/po/de/omr-tracker.po +++ b/luci-app-omr-tracker/po/de/omr-tracker.po @@ -10,33 +10,166 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 +#, fuzzy msgid "" -"Always ping gateway, then test connection by ping or dns. None mode only " -"ping gateway." +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." msgstr "" "Die Auswahl 'immer' prüft den Server auf ping und dann alle Anschlüsse auf " "Ping und DNS-Verfügbarkeit. 'nie' führt nur Server-Pings durch." +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Check if connection work with http by sending a request to server" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 msgid "Defaults Settings" msgstr "Werkseinstellungen" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:165 +msgid "Enable" +msgstr "" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 msgid "Hosts" msgstr "Hostsysteme" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Hosts IPv6" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:154 +msgid "Interfaces" +msgstr "" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "Mail alert" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Must be IPs and not domains" +msgstr "" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 msgid "OMR-Tracker" msgstr "OMR-Tracker" -msgid "OMR-Tracker detect when a connection is down" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +#, fuzzy +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" msgstr "Der OMR_Tracker erkennt Störungen an Anschlüssen." +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart if down" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart interface if detected as down" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:180 msgid "Retry interval (s)" msgstr "Wiederhol-Abstand (in Sekunden)" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Send a mail when connection state change" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Server http test" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:168 msgid "Timeout (s)" msgstr "Wartezeit (in Sekunden)" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:174 msgid "Tries" msgstr "Versuche" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "Type" msgstr "Typ" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:186 +msgid "Wait after a failed test (s)" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "" diff --git a/luci-app-omr-tracker/po/de/omr-tracker.po~ b/luci-app-omr-tracker/po/de/omr-tracker.po~ new file mode 100644 index 000000000..41b194360 --- /dev/null +++ b/luci-app-omr-tracker/po/de/omr-tracker.po~ @@ -0,0 +1,151 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-14 08:04+0000\n" +"Last-Translator: Andreas Dorfer \n" +"Language-Team: German \n" +"Language: de\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +#, fuzzy +#| msgid "" +#| "Always ping gateway, then test connection by ping or dns. None mode only " +#| "ping gateway." +msgid "" +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." +msgstr "" +"Die Auswahl 'immer' prüft den Server auf ping und dann alle Anschlüsse auf " +"Ping und DNS-Verfügbarkeit. 'nie' führt nur Server-Pings durch." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +msgid "Defaults Settings" +msgstr "Werkseinstellungen" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:146 +msgid "Enable" +msgstr "" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:187 +msgid "Hosts" +msgstr "Hostsysteme" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:135 +msgid "Interfaces" +msgstr "" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +msgid "Mail alert" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Must be IPs and not domains" +msgstr "" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 +msgid "OMR-Tracker" +msgstr "OMR-Tracker" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +#, fuzzy +#| msgid "OMR-Tracker detect when a connection is down" +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" +msgstr "Der OMR_Tracker erkennt Störungen an Anschlüssen." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:161 +msgid "Retry interval (s)" +msgstr "Wiederhol-Abstand (in Sekunden)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +msgid "Send a mail when connection state change" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +msgid "Timeout (s)" +msgstr "Wartezeit (in Sekunden)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:155 +msgid "Tries" +msgstr "Versuche" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +msgid "Type" +msgstr "Typ" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:167 +msgid "Wait after a failed test (s)" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "" diff --git a/luci-app-omr-tracker/po/fr/omr-tracker.po b/luci-app-omr-tracker/po/fr/omr-tracker.po index 2c4542b88..16d168881 100755 --- a/luci-app-omr-tracker/po/fr/omr-tracker.po +++ b/luci-app-omr-tracker/po/fr/omr-tracker.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-03 12:39+0000\n" +"PO-Revision-Date: 2021-05-17 17:36+0000\n" "Last-Translator: Weblate Admin \n" "Language-Team: French \n" @@ -11,35 +11,179 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "Ajouter" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "" -"Always ping gateway, then test connection by ping or dns. None mode only " -"ping gateway." +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." msgstr "" -"Ping toujours la passerelle, puis teste la connexion par ping ou DNS. Le " -"mode \"none\" ping uniquement la passerelle." +"Ping toujours la passerelle, puis teste la connexion par ping, httping ou " +"DNS. Le mode \"none\" ping uniquement la passerelle." +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Check if connection work with http by sending a request to server" +msgstr "" +"Vérifiez si la connexion fonctionne avec http en envoyant une demande au " +"serveur" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 msgid "Defaults Settings" msgstr "Paramètres par défaut" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "" +"Détectez si le proxy est en panne et arrêtez la redirection du trafic dessus." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "" +"Détectez si le serveur est en panne et utilisez le serveur de sauvegarde " +"défini dans ce cas." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:165 +msgid "Enable" +msgstr "Activer" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "Accorder l'accès UCI pour luci-app-tracker" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 msgid "Hosts" msgstr "Hôtes" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Hosts IPv6" +msgstr "Hôtes IPv6" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "Les adresses IP ou les domaines doivent être disponibles via http" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:154 +msgid "Interfaces" +msgstr "Interfaces" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "Invalide" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "Mail alert" +msgstr "Alerte mail" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Must be IPs and not domains" +msgstr "Doit être des adresses IP et non des domaines" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 msgid "OMR-Tracker" msgstr "OMR-Tracker" -msgid "OMR-Tracker detect when a connection is down" -msgstr "OMR-Tracker détecte quand une connexion ne fonctionne plus" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" +msgstr "" +"OMR-Tracker crée les routes nécessaires et détecte lorsqu'une connexion est " +"en panne" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "Paramètres de suivi du proxy" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart if down" +msgstr "Redémarrer si en panne" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart interface if detected as down" +msgstr "Redémarrez l'interface si elle est détectée comme étant en panne" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:180 msgid "Retry interval (s)" msgstr "Intervalle entre les essais (s)" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Send a mail when connection state change" +msgstr "Envoyer un e-mail lorsque l'état de la connexion change" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" +"Envoyer un mail lorsque l'état de la connexion change. Vous devez configurer " +"les paramètres e-mail ici." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Server http test" +msgstr "Test http du serveur" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "Paramètres de suivi du serveur" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:168 msgid "Timeout (s)" msgstr "Délais d'attente (s)" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:174 msgid "Tries" msgstr "Essais" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "Type" msgstr "Type" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:186 +msgid "Wait after a failed test (s)" +msgstr "Attendre après un test échoué (s)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "" +"Lorsque le tracker est désactivé, le basculement de connexion est également " +"désactivé" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "" +"Lorsque le tracker est désactivé, le basculement du serveur est également " +"désactivé" diff --git a/luci-app-omr-tracker/po/fr/omr-tracker.po~ b/luci-app-omr-tracker/po/fr/omr-tracker.po~ new file mode 100644 index 000000000..7cb6f825e --- /dev/null +++ b/luci-app-omr-tracker/po/fr/omr-tracker.po~ @@ -0,0 +1,159 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2021-04-30 16:16+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "Ajouter" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +msgid "" +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." +msgstr "" +"Ping toujours la passerelle, puis teste la connexion par ping, httping ou " +"DNS. Le mode \"none\" ping uniquement la passerelle." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +msgid "Defaults Settings" +msgstr "Paramètres par défaut" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "" +"Détectez si le proxy est en panne et arrêtez la redirection du trafic dessus." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "" +"Détectez si le serveur est en panne et utilisez le serveur de sauvegarde " +"défini dans ce cas." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:146 +msgid "Enable" +msgstr "Activer" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "Accorder l'accès UCI pour luci-app-tracker" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:187 +msgid "Hosts" +msgstr "Hôtes" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "Les adresses IP ou les domaines doivent être disponibles via http" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:135 +msgid "Interfaces" +msgstr "Interfaces" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "Invalide" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +msgid "Mail alert" +msgstr "Alerte mail" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Must be IPs and not domains" +msgstr "Doit être des adresses IP et non des domaines" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 +msgid "OMR-Tracker" +msgstr "OMR-Tracker" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" +msgstr "" +"OMR-Tracker crée les routes nécessaires et détecte lorsqu'une connexion est " +"en panne" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "Paramètres de suivi du proxy" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:161 +msgid "Retry interval (s)" +msgstr "Intervalle entre les essais (s)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +msgid "Send a mail when connection state change" +msgstr "Envoyer un e-mail lorsque l'état de la connexion change" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" +"Envoyer un mail lorsque l'état de la connexion change. Vous devez configurer " +"les paramètres e-mail ici." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "Paramètres de suivi du serveur" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +msgid "Timeout (s)" +msgstr "Délais d'attente (s)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:155 +msgid "Tries" +msgstr "Essais" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +msgid "Type" +msgstr "Type" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:167 +msgid "Wait after a failed test (s)" +msgstr "Attendre après un test échoué (s)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "" +"Lorsque le tracker est désactivé, le basculement de connexion est également " +"désactivé" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "" +"Lorsque le tracker est désactivé, le basculement du serveur est également " +"désactivé" diff --git a/luci-app-omr-tracker/po/it/omr-tracker.po b/luci-app-omr-tracker/po/it/omr-tracker.po index 2e88f23f7..4257d56b1 100755 --- a/luci-app-omr-tracker/po/it/omr-tracker.po +++ b/luci-app-omr-tracker/po/it/omr-tracker.po @@ -10,33 +10,166 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.0.4\n" +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 +#, fuzzy msgid "" -"Always ping gateway, then test connection by ping or dns. None mode only " -"ping gateway." +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." msgstr "" "Esegui sempre il ping del gateway, quindi verifica la connessione tramite " "ping o DNS." +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Check if connection work with http by sending a request to server" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 msgid "Defaults Settings" msgstr "Impostazioni predefinite" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:165 +msgid "Enable" +msgstr "" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 msgid "Hosts" msgstr "" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Hosts IPv6" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:154 +msgid "Interfaces" +msgstr "" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "Mail alert" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Must be IPs and not domains" +msgstr "" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 msgid "OMR-Tracker" msgstr "" -msgid "OMR-Tracker detect when a connection is down" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +#, fuzzy +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" msgstr "OMR-Tracker rileva quando una connessione è interrotta" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart if down" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart interface if detected as down" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:180 msgid "Retry interval (s)" msgstr "Intervallo di ripetizione (s)" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Send a mail when connection state change" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Server http test" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:168 msgid "Timeout (s)" msgstr "" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:174 msgid "Tries" msgstr "Tentativi" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "Type" msgstr "Tipo" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:186 +msgid "Wait after a failed test (s)" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "" diff --git a/luci-app-omr-tracker/po/it/omr-tracker.po~ b/luci-app-omr-tracker/po/it/omr-tracker.po~ new file mode 100644 index 000000000..61ebe850d --- /dev/null +++ b/luci-app-omr-tracker/po/it/omr-tracker.po~ @@ -0,0 +1,151 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-09-21 12:51+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: Italian \n" +"Language: it\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +#, fuzzy +#| msgid "" +#| "Always ping gateway, then test connection by ping or dns. None mode only " +#| "ping gateway." +msgid "" +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." +msgstr "" +"Esegui sempre il ping del gateway, quindi verifica la connessione tramite " +"ping o DNS." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +msgid "Defaults Settings" +msgstr "Impostazioni predefinite" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:146 +msgid "Enable" +msgstr "" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:187 +msgid "Hosts" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:135 +msgid "Interfaces" +msgstr "" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +msgid "Mail alert" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Must be IPs and not domains" +msgstr "" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 +msgid "OMR-Tracker" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +#, fuzzy +#| msgid "OMR-Tracker detect when a connection is down" +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" +msgstr "OMR-Tracker rileva quando una connessione è interrotta" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:161 +msgid "Retry interval (s)" +msgstr "Intervallo di ripetizione (s)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +msgid "Send a mail when connection state change" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +msgid "Timeout (s)" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:155 +msgid "Tries" +msgstr "Tentativi" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +msgid "Type" +msgstr "Tipo" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:167 +msgid "Wait after a failed test (s)" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "" diff --git a/luci-app-omr-tracker/po/oc/omr-tracker.po b/luci-app-omr-tracker/po/oc/omr-tracker.po index 178b33f23..0ed531bb0 100755 --- a/luci-app-omr-tracker/po/oc/omr-tracker.po +++ b/luci-app-omr-tracker/po/oc/omr-tracker.po @@ -10,33 +10,166 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n > 1;\n" "X-Generator: Weblate 4.0.4\n" +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 +#, fuzzy msgid "" -"Always ping gateway, then test connection by ping or dns. None mode only " -"ping gateway." +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." msgstr "" "Totjorn enviar un ping a la palanca puèi la connexion via ping o DNS. Lo " "mòde \"none\" ping sonque la palanca." +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Check if connection work with http by sending a request to server" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 msgid "Defaults Settings" msgstr "Paramètres per defaut" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:165 +msgid "Enable" +msgstr "" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 msgid "Hosts" msgstr "Òstes" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Hosts IPv6" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:154 +msgid "Interfaces" +msgstr "" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "Mail alert" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Must be IPs and not domains" +msgstr "" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 msgid "OMR-Tracker" msgstr "OMR-Tracker" -msgid "OMR-Tracker detect when a connection is down" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +#, fuzzy +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" msgstr "OMR-Tracker detècta quand una connexion fonciona pas mai" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart if down" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart interface if detected as down" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:180 msgid "Retry interval (s)" msgstr "Interval entre ensages" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Send a mail when connection state change" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Server http test" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:168 msgid "Timeout (s)" msgstr "Relambi d'espèra (s)" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:174 msgid "Tries" msgstr "Ensages" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "Type" msgstr "Tipe" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:186 +msgid "Wait after a failed test (s)" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "" diff --git a/luci-app-omr-tracker/po/oc/omr-tracker.po~ b/luci-app-omr-tracker/po/oc/omr-tracker.po~ new file mode 100644 index 000000000..6e2159871 --- /dev/null +++ b/luci-app-omr-tracker/po/oc/omr-tracker.po~ @@ -0,0 +1,151 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2020-08-18 17:37+0000\n" +"Last-Translator: Quentin PAGÈS \n" +"Language-Team: Occitan \n" +"Language: oc\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.4\n" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +#, fuzzy +#| msgid "" +#| "Always ping gateway, then test connection by ping or dns. None mode only " +#| "ping gateway." +msgid "" +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." +msgstr "" +"Totjorn enviar un ping a la palanca puèi la connexion via ping o DNS. Lo " +"mòde \"none\" ping sonque la palanca." + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +msgid "Defaults Settings" +msgstr "Paramètres per defaut" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:146 +msgid "Enable" +msgstr "" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:187 +msgid "Hosts" +msgstr "Òstes" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:135 +msgid "Interfaces" +msgstr "" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +msgid "Mail alert" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Must be IPs and not domains" +msgstr "" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 +msgid "OMR-Tracker" +msgstr "OMR-Tracker" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +#, fuzzy +#| msgid "OMR-Tracker detect when a connection is down" +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" +msgstr "OMR-Tracker detècta quand una connexion fonciona pas mai" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:161 +msgid "Retry interval (s)" +msgstr "Interval entre ensages" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +msgid "Send a mail when connection state change" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +msgid "Timeout (s)" +msgstr "Relambi d'espèra (s)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:155 +msgid "Tries" +msgstr "Ensages" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +msgid "Type" +msgstr "Tipe" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:167 +msgid "Wait after a failed test (s)" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "" diff --git a/luci-app-omr-tracker/po/templates/omr-tracker.pot b/luci-app-omr-tracker/po/templates/omr-tracker.pot index f71762609..4cdce9be1 100755 --- a/luci-app-omr-tracker/po/templates/omr-tracker.pot +++ b/luci-app-omr-tracker/po/templates/omr-tracker.pot @@ -6,12 +6,17 @@ msgid "Add" msgstr "" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "" "Always ping gateway, then test connection by ping, httping or dns. None mode " "only ping gateway." msgstr "" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Check if connection work with http by sending a request to server" +msgstr "" + #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 msgid "Defaults Settings" msgstr "" @@ -27,7 +32,7 @@ msgstr "" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:146 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:165 msgid "Enable" msgstr "" @@ -36,16 +41,21 @@ msgid "Grant UCI access for luci-app-omr-tracker" msgstr "" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:187 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 msgid "Hosts" msgstr "" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Hosts IPv6" +msgstr "" + #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 msgid "IPs or domains must be available over http" msgstr "" -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:135 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:154 msgid "Interfaces" msgstr "" @@ -53,12 +63,15 @@ msgstr "" msgid "Invalid" msgstr "" -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 msgid "Mail alert" msgstr "" -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 msgid "Must be IPs and not domains" msgstr "" @@ -77,23 +90,38 @@ msgstr "" msgid "Proxy tracker Settings" msgstr "" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart if down" +msgstr "" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart interface if detected as down" +msgstr "" + #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:161 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:180 msgid "Retry interval (s)" msgstr "" -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 msgid "Send a mail when connection state change" msgstr "" -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:179 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 msgid "" "Send a mail when connection status change. You need to configure e-mail " "settings here." msgstr "" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Server http test" +msgstr "" + #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 msgid "Server tracker Settings" msgstr "" @@ -101,26 +129,26 @@ msgstr "" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:168 msgid "Timeout (s)" msgstr "" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:155 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:174 msgid "Tries" msgstr "" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:173 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "Type" msgstr "" #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 #: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 -#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:167 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:186 msgid "Wait after a failed test (s)" msgstr "" diff --git a/luci-app-omr-tracker/po/zh_Hans/omr-tracker.po b/luci-app-omr-tracker/po/zh_Hans/omr-tracker.po index 856001abd..43d1ab8dc 100755 --- a/luci-app-omr-tracker/po/zh_Hans/omr-tracker.po +++ b/luci-app-omr-tracker/po/zh_Hans/omr-tracker.po @@ -1,40 +1,173 @@ msgid "" msgstr "" -"PO-Revision-Date: 2020-12-04 16:02+0000\n" -"Last-Translator: antrouter \n" +"PO-Revision-Date: 2021-05-13 21:38+0000\n" +"Last-Translator: justbin <419989953@qq.com>\n" "Language-Team: Chinese (Simplified) \n" "Language: zh_Hans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.0.4\n" +"X-Generator: Weblate 4.6.1\n" +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:8 +msgid "Add" +msgstr "添加" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "" -"Always ping gateway, then test connection by ping or dns. None mode only " -"ping gateway." -msgstr "始终对网关执行ping操作,然后通过ping或dns测试连接,无模式仅可ping网关." +"Always ping gateway, then test connection by ping, httping or dns. None mode " +"only ping gateway." +msgstr "总是ping网关,然后通过ping, http或dns测试连接。无模式仅ping网关。" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Check if connection work with http by sending a request to server" +msgstr "通过向服务器发送请求,检查连接是否与http工作" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 msgid "Defaults Settings" -msgstr "蚂蚁默认设置" +msgstr "默认设置" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Detect if Proxy is down and stop traffic redirection over it." +msgstr "检测代理是否关闭并停止通过它的流量重定向。" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Detect if Server is down and use defined backup server in this case." +msgstr "检测服务器是否关闭,并在这种情况下使用定义的备份服务器。" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:165 +msgid "Enable" +msgstr "启用" + +#: luci-app-omr-tracker/root/usr/share/rpcd/acl.d/luci-app-omr-tracker.json:3 +msgid "Grant UCI access for luci-app-omr-tracker" +msgstr "授权UCI访问聚合跟踪器" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 msgid "Hosts" msgstr "主机" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Hosts IPv6" +msgstr "IPv6 主机" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:44 +msgid "IPs or domains must be available over http" +msgstr "ip或域必须在http上可用" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:154 +msgid "Interfaces" +msgstr "接口" + +#: luci-app-omr-tracker/luasrc/view/omr-tracker/cbi-select-add.htm:9 +msgid "Invalid" +msgstr "无效的" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "Mail alert" +msgstr "邮件提醒" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:144 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:149 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:219 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:224 +msgid "Must be IPs and not domains" +msgstr "必须是ip而不是域" + +#: luci-app-omr-tracker/luasrc/controller/omr-tracker.lua:5 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:5 +#: luci-app-omr-tracker/root/usr/share/luci/menu.d/luci-app-omr-tracker.json:3 msgid "OMR-Tracker" -msgstr "蚂蚁跟踪器" +msgstr "聚合跟踪器" -msgid "OMR-Tracker detect when a connection is down" -msgstr "蚂蚁跟踪器检测网卡何时断开" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:87 +msgid "" +"OMR-Tracker create needed routes and detect when a connection is down or up" +msgstr "聚合跟踪器创建所需的路径,并检测连接何时断开或接通" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:7 +msgid "Proxy tracker Settings" +msgstr "代理跟踪设置" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart if down" +msgstr "如果关闭,重新启动" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:137 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:212 +msgid "Restart interface if detected as down" +msgstr "如果检测到接口关闭,重新启动接口" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:32 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:75 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:105 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:180 msgid "Retry interval (s)" -msgstr "重试间隔 (秒)" +msgstr "重试时间间隔(秒)" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:130 +msgid "Send a mail when connection state change" +msgstr "当连接状态改变时发送邮件" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:205 +msgid "" +"Send a mail when connection status change. You need to configure e-mail " +"settings here." +msgstr "" +"当连接状态发生变化时发送邮件。你需要配置电子邮件设置这里。" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:123 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:198 +msgid "Server http test" +msgstr "服务器http测试" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:50 +msgid "Server tracker Settings" +msgstr "服务器跟踪设置" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:20 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:63 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:93 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:168 msgid "Timeout (s)" -msgstr "超时(s)" +msgstr "超时(秒)" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:26 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:69 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:99 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:174 msgid "Tries" -msgstr "尝试多少次" +msgstr "尝试" +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:117 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:192 msgid "Type" msgstr "类型" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:38 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:81 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:111 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:186 +msgid "Wait after a failed test (s)" +msgstr "在测试失败后等待(秒)" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:17 +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:90 +msgid "When tracker is disabled, connection failover is also disabled" +msgstr "禁用跟踪器时,也禁用连接故障转移" + +#: luci-app-omr-tracker/luasrc/model/cbi/omr-tracker.lua:60 +msgid "When tracker is disabled, server failover is also disabled" +msgstr "禁用跟踪器时,也禁用服务器故障转移" diff --git a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua index 077dd065c..3d243b210 100755 --- a/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua +++ b/luci-app-openmptcprouter/luasrc/controller/openmptcprouter.lua @@ -176,8 +176,8 @@ function wizard_add() ucic:set("sqm","wan" .. i,"verbosity","5") ucic:set("sqm","wan" .. i,"download","0") ucic:set("sqm","wan" .. i,"upload","0") - ucic:set("sqm","wan" .. i,"iqdisc_opts","autorate-ingress nat dual-dsthost") - ucic:set("sqm","wan" .. i,"eqdisc_opts","nat dual-srchost") + ucic:set("sqm","wan" .. i,"iqdisc_opts","autorate-ingress dual-dsthost") + ucic:set("sqm","wan" .. i,"eqdisc_opts","dual-srchost") ucic:save("sqm") ucic:commit("sqm") @@ -349,14 +349,16 @@ function wizard_add() ucic:set("sqm",intf,"qdisc","fq_codel") ucic:set("sqm",intf,"script","simple.qos") ucic:set("sqm",intf,"qdisc_advanced","0") - ucic:set("sqm",intf,"linklayer","none") + ucic:set("sqm",intf,"linklayer","atm") + ucic:set("sqm",intf,"overhead","40") ucic:set("sqm",intf,"enabled","0") ucic:set("sqm",intf,"debug_logging","0") ucic:set("sqm",intf,"verbosity","5") ucic:set("sqm",intf,"download","0") ucic:set("sqm",intf,"upload","0") - ucic:set("sqm",intf,"iqdisc_opts","autorate-ingress nat dual-dsthost") - ucic:set("sqm",intf,"eqdisc_opts","nat dual-srchost") + ucic:set("sqm",intf,"iqdisc_opts","autorate-ingress") + --ucic:set("sqm",intf,"iqdisc_opts","autorate-ingress dual-dsthost") + --ucic:set("sqm",intf,"eqdisc_opts","dual-srchost") end if downloadspeed ~= "0" and downloadspeed ~= "" then @@ -364,6 +366,7 @@ function wizard_add() ucic:set("sqm",intf,"download",math.ceil(downloadspeed*95/100)) ucic:set("qos",intf,"download",math.ceil(downloadspeed*95/100)) else + ucic:delete("network",intf,"downloadspeed") ucic:set("sqm",intf,"download","0") ucic:set("qos",intf,"download","0") end @@ -372,17 +375,15 @@ function wizard_add() ucic:set("sqm",intf,"upload",math.ceil(uploadspeed*95/100)) ucic:set("qos",intf,"upload",math.ceil(uploadspeed*95/100)) else + ucic:delete("network",intf,"uploadspeed") ucic:set("sqm",intf,"upload","0") ucic:set("qos",intf,"upload","0") end - if downloadspeed ~= "0" and downloadspeed ~= "" and uploadspeed ~= "0" and uploadspeed ~= "" then - ucic:set("sqm",intf,"enabled","0") - ucic:set("qos",intf,"enabled","0") - end if sqmenabled == "1" then - ucic:set("sqm",intf,"iqdisc_opts","autorate-ingress nat dual-dsthost") - ucic:set("sqm",intf,"eqdisc_opts","nat dual-srchost") + ucic:set("sqm",intf,"iqdisc_opts","autorate-ingress") + --ucic:set("sqm",intf,"iqdisc_opts","autorate-ingress dual-dsthost") + --ucic:set("sqm",intf,"eqdisc_opts","dual-srchost") ucic:set("sqm",intf,"enabled","1") ucic:set("qos",intf,"enabled","1") else @@ -510,6 +511,18 @@ function wizard_add() ucic:set("openmptcprouter","settings","country",country) ucic:save("openmptcprouter") + -- Get DNS64 + local dns64 = luci.http.formvalue("dns64") or "0" + ucic:set("openmptcprouter","settings","dns64",dns64) + ucic:save("openmptcprouter") + if dns64 == "1" then + ucic:set("unbound","ub_main","dns64","1") + ucic:set("unbound","ub_main","validator","0") + else + ucic:set("unbound","ub_main","dns64","0") + + end + -- Get Proxy set by default local default_proxy = luci.http.formvalue("default_proxy") or "shadowsocks" if default_proxy == "shadowsocks" and serversnb > 0 and serversnb > disablednb then @@ -895,12 +908,12 @@ function wizard_add() luci.sys.call("/etc/init.d/glorytun-udp restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/mlvpn restart >/dev/null 2>/dev/null") --luci.sys.call("/etc/init.d/ubond restart >/dev/null 2>/dev/null") + luci.sys.call("/etc/init.d/mptcpovervpn restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/openvpn restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/openvpnbonding restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/dsvpn restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/omr-tracker start >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/omr-6in4 restart >/dev/null 2>/dev/null") - luci.sys.call("/etc/init.d/mptcpovervpn restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/vnstat restart >/dev/null 2>/dev/null") luci.sys.call("/etc/init.d/v2ray restart >/dev/null 2>/dev/null") luci.http.redirect(luci.dispatcher.build_url("admin/system/" .. menuentry:lower() .. "/status")) @@ -988,6 +1001,22 @@ function settings_add() local disablegwping = luci.http.formvalue("disablegwping") or "0" ucic:set("openmptcprouter","settings","disablegwping",disablegwping) + -- VPS timeout + local status_vps_timeout = luci.http.formvalue("status_vps_timeout") or "1" + ucic:set("openmptcprouter","settings","status_vps_timeout",status_vps_timeout) + + -- IP timeout + local status_getip_timeout = luci.http.formvalue("status_getip_timeout") or "1" + ucic:set("openmptcprouter","settings","status_getip_timeout",status_getip_timeout) + + -- Enable/disable loop detection + local disableloopdetection = luci.http.formvalue("disableloopdetection") or "0" + ucic:set("openmptcprouter","settings","disableloopdetection",disableloopdetection) + + -- Enable/disable http test + local disableserverhttptest = luci.http.formvalue("disableserverhttptest") or "0" + ucic:set("openmptcprouter","settings","disableserverhttptest",disableserverhttptest) + -- Enable/disable renaming intf local disableintfrename = luci.http.formvalue("disableintfrename") or "0" ucic:set("openmptcprouter","settings","disableintfrename",disableintfrename) @@ -997,9 +1026,13 @@ function settings_add() ucic:set("openmptcprouter","settings","defaultgw",disabledefaultgw) -- Enable/disable tracebox - local tracebox = luci.http.formvalue("tracebox") or "1" + local tracebox = luci.http.formvalue("disabletracebox") or "1" ucic:set("openmptcprouter","settings","tracebox",tracebox) + -- Enable/disable ModemManager + local modemmanager = luci.http.formvalue("disablemodemmanager") or "1" + ucic:set("openmptcprouter","settings","modemmanager",modemmanager) + -- Enable/disable server ping local disableserverping = luci.http.formvalue("disableserverping") or "0" ucic:set("openmptcprouter","settings","disableserverping",disableserverping) @@ -1008,6 +1041,10 @@ function settings_add() local shadowsocksudp = luci.http.formvalue("shadowsocksudp") or "0" ucic:set("openmptcprouter","settings","shadowsocksudp",shadowsocksudp) + -- Enable/disable nDPI + local ndpi = luci.http.formvalue("ndpi") or "1" + ucic:set("openmptcprouter","settings","ndpi",ndpi) + -- Enable/disable fast open local disablefastopen = luci.http.formvalue("disablefastopen") or "0" if disablefastopen == "0" then @@ -1069,6 +1106,13 @@ function settings_add() ucic:set("openmptcprouter","settings","scaling_governor",scaling_governor) end + -- Enable/disable Qualcomm Shortcut FE + local sfe_enabled = luci.http.formvalue("sfe_enabled") or "0" + ucic:set("openmptcprouter","settings","sfe_enabled",sfe_enabled) + local sfe_bridge = luci.http.formvalue("sfe_bridge") or "0" + ucic:set("openmptcprouter","settings","sfe_bridge",sfe_bridge) + + ucic:save("openmptcprouter") ucic:commit("openmptcprouter") @@ -1087,7 +1131,7 @@ function update_vps() local update_vps = luci.http.formvalue("flash") or "" if update_vps ~= "" then local ut = require "luci.util" - local result = ut.ubus("openmptcprouter", "update_vps", {}) + local result = ut.ubus("openmptcprouter", "updateVPS", {}) end return end diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm index 59002637f..99e83b481 100755 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/settings.htm @@ -254,6 +254,27 @@ +
+ +
+ "> +
+
+ <%:Timeout for VPS checks on status pages%> +
+
+
+
+ +
+ "> +
+
+ <%:Timeout for retrieving WANs IP on status pages%> +
+
+
+
@@ -290,6 +311,16 @@
+
+ +
+ checked<% end %>> +
+
+ <%:Disable route loop detection%> +
+
+
@@ -300,6 +331,26 @@
+
+ +
+ checked<% end %>> +
+
+ <%:Disable nDPI, used for protocols in OMR-ByPass%> +
+
+
+
+ +
+ checked<% end %>> +
+
+ <%:Disable ModemManager%> +
+
+
@@ -322,6 +373,28 @@
+ <% + if nixio.fs.access("/lib/modules/" .. nixio.uname().release .. "/shortcut-fe.ko") then + %> +
+
+ <%:Qualcomm Shortcut FE driver%> +
+
+ +
+ checked<% end %>> +
+
+
+ +
+ checked<% end %>> +
+
+
+ <% end %> + <% if nixio.fs.access("/sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq") then %>
<%:Systems settings%> diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm index d0eaafee4..5f248ab31 100755 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wanstatus.htm @@ -240,12 +240,15 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm } else if (mArray.openmptcprouter.wan_addr6 != "" && mArray.openmptcprouter.service_addr == "127.0.0.1") { var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr6); - } else if (mArray.openmptcprouter.wan_addr != "") + } else if (mArray.openmptcprouter.direct_output == false) + { + var title = String.format("%s (%s)", mArray.openmptcprouter.vps_hostname, mArray.openmptcprouter.wan_addr6); + } else if (mArray.openmptcprouter.wan_addr != "" && mArray.openmptcprouter.direct_output == true) { var title = String.format("%s (%s)", _('Direct output'), mArray.openmptcprouter.wan_addr); statusMessageClass = "warning"; statusIcon = "<%=resource%>/openmptcprouter/images/statusWarning.png"; - } else if (mArray.openmptcprouter.wan_addr6 != "") + } else if (mArray.openmptcprouter.wan_addr6 != "" && mArray.openmptcprouter.direct_output == true) { var title = String.format("%s (%s)", _('Direct output'), mArray.openmptcprouter.wan_addr6); statusMessageClass = "warning"; @@ -460,6 +463,7 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm var multipath_state = mArray.wans[i].multipath_state; var duplicateif = mArray.wans[i].duplicateif; var duplicatemac = mArray.wans[i].duplicatemac; + var loop = mArray.wans[i].loop; // Generate template if(mArray.openmptcprouter.remote_from_lease == true && mArray.wans.length == 1) { @@ -619,6 +623,10 @@ local statuslogo = ucic:get("openmptcprouter","settings","statuslogo") or "openm statusMessage += '<%:Network interface MAC address duplicated%>' + '
'; statusMessageClass = "error"; } + if(loop) + { + statusMessage += '<%:Looping route detected%>' + '
'; + } if(ipv6_discover == 'DETECTED') { statusMessage += '<%:IPv6 route received%>' + '
' diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index 21f01d1b2..2c33cfa2d 100755 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -35,6 +35,17 @@ return t end + alltty = {} + iftty = luci.sys.exec("timeout 1 /usr/bin/mmcli -L") + for listtty in iftty:gmatch("([^\r\n]*)[\r\n]") do + modemid = luci.util.trim(luci.sys.exec("echo '" .. listtty .. "' | awk -F' ' '{print $1}' | awk -F/ '{print $6}'")) + if modemid ~= '' then + modeminfo = luci.sys.exec("timeout 1 /usr/bin/mmcli -m " .. modemid .. " --output-keyvalue") + tty = luci.util.trim(luci.sys.exec("echo '" .. modeminfo .. "' | grep 'modem.generic.device ' | awk -F': ' '{print $2}'")) + table.insert(alltty, tty) + end + end + %> @@ -49,7 +60,7 @@ } <% if stderr and #stderr > 0 then %>
<%=pcdata(stderr)%>
<% end %> -
+

<%:Wizard%>

@@ -118,7 +129,7 @@
- checked<% end %>/> + checked <% end %>/>
<%:Only one server can be master, else all servers are set as backup.%> @@ -132,7 +143,7 @@
- checked<% end %>/> + checked <% end %>/>
<% @@ -194,6 +205,16 @@
+
+ +
+ checked <% end %>/> +
+
+ <%:If host support NAT64, you can enable DNS64 support.%> +
+
+
<%:Proxy settings%> @@ -367,7 +388,7 @@
<%:MPTCP over VPN settings%> -
<%:MPTCP over VPN should be used only when Multipath TCP is blocked on a connection.%>
+
<%:MPTCP over VPN should be used only when Multipath TCP is blocked on a connection.%> <%:Only work with Shadowsocks as proxy.%>
@@ -449,7 +470,7 @@ <% iffind=0 for _, ifacea in ipairs(ifaces) do - if not (ifacea == "lo" or ifacea == "6in4-omr6in4" or ifacea == "mlvpn0" or ifacea:match("^ifb.*") or ifacea:match("^sit.*") or ifacea:match("^gre.*") or ifacea:match("^ip6.*") or ifacea:match("^teql.*") or ifacea:match("^erspan.*") or ifacea:match("^tun.*")) and device_notvirtual(ifacea) then + if not (ifacea == "lo" or ifacea == "6in4-omr6in4" or ifacea == "mlvpn0" or ifacea:match("^ifb.*") or ifacea:match("^sit.*") or ifacea:match("^gre.*") or ifacea:match("^ip6.*") or ifacea:match("^teql.*") or ifacea:match("^erspan.*") or ifacea:match("^tun.*") or ifacea:match("^bond.*")) and device_notvirtual(ifacea) then if uci:get("network",ifname,"proto") ~= "macvlan" then %> @@ -554,7 +575,7 @@ <% iffind=0 - iftty = luci.sys.exec("/usr/bin/mmcli -L") - for listtty in iftty:gmatch("([^\r\n]*)[\r\n]") do - modemid = luci.util.trim(luci.sys.exec("echo '" .. listtty .. "' | awk -F' ' '{print $1}' | awk -F/ '{print $6}'")) - if modemid ~= '' then - modeminfo = luci.sys.exec("/usr/bin/mmcli -m " .. modemid .. " --output-keyvalue") - tty = luci.util.trim(luci.sys.exec("echo '" .. modeminfo .. "' | grep 'modem.generic.device ' | awk -F': ' '{print $2}'")) + for _, tty in ipairs(alltty) do %> <% - end end if iffind == 0 and uci:get("network",ifname,"device") ~= nil then %> @@ -956,7 +971,7 @@
- +
diff --git a/luci-app-sysupgrade/po/fr/sysupgrade.po b/luci-app-sysupgrade/po/fr/sysupgrade.po index 45f8c0ba5..8195816c5 100755 --- a/luci-app-sysupgrade/po/fr/sysupgrade.po +++ b/luci-app-sysupgrade/po/fr/sysupgrade.po @@ -53,7 +53,7 @@ msgstr "Redémarrage de l'appareil - veuillez patienter !" msgid "Request firmware" msgstr "Demander le micrologiciel" -#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:110 +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:113 msgid "Search for upgrades" msgstr "Rechercher des mises à jour" @@ -61,7 +61,7 @@ msgstr "Rechercher des mises à jour" msgid "Searching for upgrades" msgstr "Recherche des mises à jour" -#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:103 +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:104 msgid "Server:" msgstr "Serveur :" diff --git a/luci-app-sysupgrade/po/fr/sysupgrade.po~ b/luci-app-sysupgrade/po/fr/sysupgrade.po~ new file mode 100644 index 000000000..45f8c0ba5 --- /dev/null +++ b/luci-app-sysupgrade/po/fr/sysupgrade.po~ @@ -0,0 +1,97 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-03-31 15:07+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "" +"Cochez \"Conserver les paramètres\" pour conserver la configuration actuelle." + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "Téléchargement du micrologiciel dans la mémoire du navigateur Web" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "" +"Recherchez et installez facilement les nouvelles versions et les mises à " +"niveau des paquets." + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "Modifier les packages installés" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "Mise à jour du micrologiciel. Ne débranchez pas l'appareil" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "Version installée :" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "Conserver les paramètres :" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "Pas de mise à jour disponible" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "Redémarrage de l'appareil - veuillez patienter !" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "Demander le micrologiciel" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:110 +msgid "Search for upgrades" +msgstr "Rechercher des mises à jour" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "Recherche des mises à jour" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:103 +msgid "Server:" +msgstr "Serveur :" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "Succès ! Veuillez recharger l'interface Web" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "Mise à jour système" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "" +"Le téléchargement du micrologiciel a échoué, veuillez réessayer en " +"rechargeant l'interface Web" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "Téléchargement du micrologiciel sur l'appareil" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "" +"L'interface Web n'a pas pu se reconnecter à votre appareil. Recharger " +"l'interface" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "Mise à jour système via rpcd et luci" diff --git a/luci-app-sysupgrade/po/ru/sysupgrade.po b/luci-app-sysupgrade/po/ru/sysupgrade.po new file mode 100644 index 000000000..742b59652 --- /dev/null +++ b/luci-app-sysupgrade/po/ru/sysupgrade.po @@ -0,0 +1,94 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "" +"Поставьте \"Сохранить настройки\", чтобы сохранить текущую конфигурацию." + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "Загружаем ПО в память вашего браузера" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "Легко ищите и устанавливайте новые версии ПО и обновления пакетов." + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "Редактировать список установленных пакетов" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "Обновляем ПО маршрутизатора. Не выключайте питание вашего устройства" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "Установленная версия:" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "Сохранить настройки:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "Обновления не найдены" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "Перезагружаем роутер, пожалуйста подождите!" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "Загрузить ПО" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:113 +msgid "Search for upgrades" +msgstr "Поиск обновлений" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "Поиск обновлений" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:104 +msgid "Server:" +msgstr "Сервер:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "Успешно! Пожалуйста обновите страницу" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "sysupgrade" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "" +"Ошибка при загрузке обновлений ПО. Для продолжения, пожалуйста обновите " +"страницу" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "Загружаем обновления ПО в память роутера" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "Проблема при подключении к роутеру. Пожалуйста обновите страницу" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "sysupgrade с использованием RPCd и LUCI" diff --git a/luci-app-sysupgrade/po/templates/sysupgrade.pot b/luci-app-sysupgrade/po/templates/sysupgrade.pot index 0c4a913f0..1ebb8dc2e 100755 --- a/luci-app-sysupgrade/po/templates/sysupgrade.pot +++ b/luci-app-sysupgrade/po/templates/sysupgrade.pot @@ -41,7 +41,7 @@ msgstr "" msgid "Request firmware" msgstr "" -#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:110 +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:113 msgid "Search for upgrades" msgstr "" @@ -49,7 +49,7 @@ msgstr "" msgid "Searching for upgrades" msgstr "" -#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:103 +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:104 msgid "Server:" msgstr "" diff --git a/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po b/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po new file mode 100644 index 000000000..e68dec985 --- /dev/null +++ b/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po @@ -0,0 +1,90 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-05-03 07:27+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "勾选保持当前配置。" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "下载固件到网页浏览器内存" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "轻松搜索和安装新版本升级固件包。" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "编辑安装包" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "设备升级中。请不要断开电源" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "安装的版本:" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "保持设置:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "没有升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "正在重启设备-请稍候!" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "请求固件" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:113 +msgid "Search for upgrades" +msgstr "搜索升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "搜索升级" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:104 +msgid "Server:" +msgstr "服务器:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "成功!请重新加载web界面" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "系统升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "轻松搜索和安装新版本的系统进行升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "上传固件到设备" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "网络界面无法重新连接到您的设备。请重新加载web界面或手动检查设备" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "通过RPCD和luci进行升级" diff --git a/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po~ b/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po~ new file mode 100644 index 000000000..85f483866 --- /dev/null +++ b/luci-app-sysupgrade/po/zh_Hans/sysupgrade.po~ @@ -0,0 +1,90 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-04-30 16:03+0000\n" +"Last-Translator: niergouge <1150108426@qq.com>\n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.5.2\n" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:90 +msgid "Check \"Keep settings\" to retain the current configuration." +msgstr "勾选保持当前配置。" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:344 +msgid "Downloading firmware to web browser memory" +msgstr "下载固件到网页浏览器内存" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:78 +msgid "Easily search and install new releases and package upgrades." +msgstr "轻松搜索和安装新版本和包升级。" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:99 +msgid "Edit installed packages" +msgstr "编辑安装包" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:269 +msgid "Flashing firmware. Don't unpower device" +msgstr "设备升级中。请不要断开电源" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:192 +msgid "Installed version:" +msgstr "安装的版本:" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:92 +msgid "Keep settings:" +msgstr "保持设置:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:215 +msgid "No upgrades available" +msgstr "没有升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:285 +msgid "Rebooting device - please wait!" +msgstr "正在重启设备-请稍候!" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:209 +msgid "Request firmware" +msgstr "请求固件" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:110 +msgid "Search for upgrades" +msgstr "搜索升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:165 +msgid "Searching for upgrades" +msgstr "搜索升级" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:103 +msgid "Server:" +msgstr "服务器:" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:289 +msgid "Success! Please reload web interface" +msgstr "成功!请重新加载web界面" + +#: luci-app-sysupgrade/luasrc/view/sysupgrade.htm:76 +#: luci-app-sysupgrade/root/usr/share/luci/menu.d/luci-app-sysupgrade.json:3 +msgid "Sysupgrade" +msgstr "系统升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:320 +msgid "Upload of firmware failed, please retry by reloading web interface" +msgstr "轻松搜索和安装新版本的系统进行升级" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:305 +msgid "Uploading firmware to device" +msgstr "上传固件到设备" + +#: luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js:299 +msgid "" +"Web interface could not reconnect to your device. Please reload web " +"interface or check device manually" +msgstr "网络界面无法重新连接到您的设备。请重新加载web界面或手动检查设备" + +#: luci-app-sysupgrade/root/usr/share/rpcd/acl.d/sysupgrade.json:3 +msgid "sysupgrade via rpcd and luci" +msgstr "通过RPCD和luci进行升级" diff --git a/luci-app-sysupgrade/root/etc/init.d/sysupgrade b/luci-app-sysupgrade/root/etc/init.d/sysupgrade new file mode 100755 index 000000000..377c67944 --- /dev/null +++ b/luci-app-sysupgrade/root/etc/init.d/sysupgrade @@ -0,0 +1,20 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2020-2021 Ycarus (Yannick Chabanois) +# Released under GPL 3. See LICENSE for the full terms. + +{ + START=99 + STOP=10 + USE_PROCD=1 +} + +start_service() +{ + if [ -f /etc/backup/installed_packages.txt ]; then + if [ "$(opkg -V0 update)" = "" ]; then + grep "\toverlay" /etc/backup/installed_packages.txt | cut -f1 | xargs -r opkg -V0 install + rm /etc/backup/installed_packages.txt + fi + fi +} + diff --git a/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js b/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js index 9002d3ee0..8cbbced97 100755 --- a/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js +++ b/luci-app-sysupgrade/root/www/luci-static/resources/sysupgrade.js @@ -65,7 +65,8 @@ function setup() { ubus_call("system", "board", {}, "release"); ubus_call("system", "board", {}, "board_name"); ubus_call("system", "info", {}, "memory"); - ubus_call("openmptcprouter", "rootfs", {}, "format"); + ubus_call("openmptcprouter", "getrootfs", {}, "format"); + ubus_call("openmptcprouter", "getefi", {}, "efi_enabled"); uci_get({ "config": "sysupgrade", "section": "server", @@ -231,6 +232,7 @@ function upgrade_request() { request_dict.target = data.release.target request_dict.profile = data.board_name request_dict.rootfs = data.format + request_dict.efi = data.efi_enabled if (data.edit_packages == true) { request_dict.packages = $("#edit_packages").value.split("\n") @@ -250,7 +252,7 @@ function upgrade_request_callback(response) { } if (sysupgrade_file != "") { data.sysupgrade_url = data.url + '/release/' + response.bin_dir + '/' + sysupgrade_file - var info_output = '

Firmware created

Created file: ' + sysupgrade_file + '

' + var info_output = '

Firmware searched

File: ' + sysupgrade_file + '

' set_status("success", info_output, false, true); show("#keep_container"); @@ -260,7 +262,7 @@ function upgrade_request_callback(response) { upgrade_button.value = "Flash firmware"; upgrade_button.onclick = download_image; } else { - set_status("danger", "Firmware build successfull but device not sysupgrade compatible!") + set_status("danger", "Device not sysupgrade compatible!") } } diff --git a/luci-mod-dashboard/po/fr/dashboard.po b/luci-mod-dashboard/po/fr/dashboard.po new file mode 100644 index 000000000..cdf32c682 --- /dev/null +++ b/luci-mod-dashboard/po/fr/dashboard.po @@ -0,0 +1,223 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-05-31 18:51+0000\n" +"Last-Translator: Weblate Admin \n" +"Language-Team: French \n" +"Language: fr\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "Actif" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "Architecture" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "BSSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "Débit" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "Canal" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "Connecté" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "Périphériques DHCP" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "Tableau de bord" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "Appareils" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "Appareils connectés" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "En panne." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "Téléchargement" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "Chiffrement" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "Version du micrologiciel" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "Ghz" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "Permettre l'accès à l'affichage de l'état DHCP" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "Permettre l'accès à l'affichage de l'état principal" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "Permettre l'acces au Status du Routage" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "Permettre l'accès du status WIFI" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "Nom d'hôte" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "Adresse IP" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "IPv4" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "Internet IPv4" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "Internet IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "Préfixe IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "Internet" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "Version du noyau" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "Charge" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "Charge moyenne" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "Heure locale" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "MAC" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "Mac" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "Modèle" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "Non connecté" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "Trafic proxy" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "SSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "Serveur" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "Signal" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "Système" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "Trafic total" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "En ligne." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "Téléverser" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "Temps de service" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "Trafic VPN" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "Version" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "Sans-fil" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "non" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "Oui" diff --git a/luci-mod-dashboard/po/ru/dashboard.po b/luci-mod-dashboard/po/ru/dashboard.po new file mode 100644 index 000000000..466e9ab42 --- /dev/null +++ b/luci-mod-dashboard/po/ru/dashboard.po @@ -0,0 +1,224 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-16 10:51+0000\n" +"Last-Translator: Dmitry Galenko \n" +"Language-Team: Russian \n" +"Language: ru\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "Активный" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "Процессор" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "BSSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "Скорость" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "Канал" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "Подключено" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "Устройства DHCP" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "Дашборд" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "Устройства" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "Подключенные устройства" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "Не работает." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "Получение" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "Шифрование" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "Версия ПО" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "GHz" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "Разрешить просмотр информации о DHCP" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "Разрешить просмотр информации основной информации" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "Разрешить просмотр информации о маршрутах" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "Разрешить просмотр информации о беспроводных сетях" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "Имя хоста" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "IP-адрес" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "IPv4" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "IPv4 Internet" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "IPv6 Internet" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "Префикс IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "Internet" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "Версия ядра" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "Загрузка" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "Средняя загрузка" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "Время хоста" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "MAC" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "Mac" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "Модель" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "Не подключено" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "Трафик через прокси" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "SSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "Сервер" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "Сигнал" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "Система" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "Трафик всего" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "Работает." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "Отправка" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "Uptime" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "Трафик VPN" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "Версия" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "Безпроводной" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "нет" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "да" diff --git a/luci-mod-dashboard/po/templates/dashboard.pot b/luci-mod-dashboard/po/templates/dashboard.pot new file mode 100644 index 000000000..018a75101 --- /dev/null +++ b/luci-mod-dashboard/po/templates/dashboard.pot @@ -0,0 +1,214 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "" diff --git a/luci-mod-dashboard/po/zh_Hans/dashboard.po b/luci-mod-dashboard/po/zh_Hans/dashboard.po new file mode 100644 index 000000000..4da85b2c8 --- /dev/null +++ b/luci-mod-dashboard/po/zh_Hans/dashboard.po @@ -0,0 +1,223 @@ +msgid "" +msgstr "" +"PO-Revision-Date: 2021-06-02 09:51+0000\n" +"Last-Translator: antrouter \n" +"Language-Team: Chinese (Simplified) \n" +"Language: zh_Hans\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.6.1\n" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:165 +msgid "Active" +msgstr "激活" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:368 +msgid "Architecture" +msgstr "构架" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:183 +msgid "BSSID" +msgstr "BSSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:177 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:245 +msgid "Bitrate" +msgstr "比特率" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:171 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:236 +msgid "Channel" +msgstr "频道" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:277 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:293 +msgid "Connected" +msgstr "连接" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:13 +msgid "DHCP Devices" +msgstr "DHCP 设备" + +#: luci-mod-dashboard/root/usr/share/luci/menu.d/luci-mod-dashboard.json:3 +msgid "Dashboard" +msgstr "仪表盘" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:136 +msgid "Devices" +msgstr "设备" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:195 +msgid "Devices Connected" +msgstr "连接的设备" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Down." +msgstr "下." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:131 +msgid "Download" +msgstr "下载" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:189 +msgid "Encryption" +msgstr "加密" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:373 +msgid "Firmware Version" +msgstr "固件版本" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:173 +msgid "GHz" +msgstr "Ghz" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:25 +msgid "Grant access to DHCP status display" +msgstr "授予访问 DHCP 状态显示的权限" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:12 +msgid "Grant access to main status display" +msgstr "授予访问主状态显示的权限" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:3 +msgid "Grant access to the system route status" +msgstr "授予对系统路由状态的访问权限" + +#: luci-mod-dashboard/root/usr/share/rpcd/acl.d/luci-mod-dashboard.json:34 +msgid "Grant access to wireless status display" +msgstr "授予访问无线状态显示的权限" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:30 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:83 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:224 +msgid "Hostname" +msgstr "主机名" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:31 +msgid "IP Address" +msgstr "IP地址" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:283 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:116 +msgid "IPv4" +msgstr "IPv4" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:274 +msgid "IPv4 Internet" +msgstr "IPv4互联网" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:305 +msgid "IPv6" +msgstr "IPv6" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:290 +msgid "IPv6 Internet" +msgstr "IPv6互联网" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:299 +msgid "IPv6 prefix" +msgstr "IPv6前缀" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "Internet" +msgstr "互联网" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:358 +msgid "Kernel Version" +msgstr "内核版本" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:241 +msgid "Load" +msgstr "负载" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:353 +msgid "Load Average" +msgstr "平均负载" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:348 +msgid "Local Time" +msgstr "本地时间" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:32 +msgid "MAC" +msgstr "MAC地址" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:121 +msgid "Mac" +msgstr "mac地址" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:179 +msgid "Mbit/s" +msgstr "Mbit/s" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:363 +msgid "Model" +msgstr "型号" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:195 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:202 +msgid "Not connected" +msgstr "未连接" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:253 +msgid "Proxy traffic" +msgstr "代理流量" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:159 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:230 +msgid "SSID" +msgstr "SSID" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:232 +msgid "Server" +msgstr "服务器" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:85 +msgid "Signal" +msgstr "信号" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:41 +msgid "System" +msgstr "系统" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:265 +msgid "Total traffic" +msgstr "总流量" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:86 +msgid "Up." +msgstr "上." + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/20_lan.js:126 +msgid "Upload" +msgstr "上传" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:247 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:343 +msgid "Uptime" +msgstr "开机时间" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:259 +msgid "VPN traffic" +msgstr "VPN流量" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:235 +msgid "Version" +msgstr "版本" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:9 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:84 +msgid "Wireless" +msgstr "无线" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "no" +msgstr "否" + +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/10_router.js:101 +#: luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js:65 +msgid "yes" +msgstr "是" diff --git a/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js b/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js index 6d8e42582..9944c0920 100755 --- a/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js +++ b/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js @@ -213,21 +213,19 @@ function iface_updown(up, id, ev, force) { function get_netmask(s, use_cfgvalue) { var readfn = use_cfgvalue ? 'cfgvalue' : 'formvalue', - addropt = s.children.filter(function(o) { return o.option == 'ipaddr'})[0], - addrvals = addropt ? L.toArray(addropt[readfn](s.section)) : [], - maskopt = s.children.filter(function(o) { return o.option == 'netmask'})[0], - maskval = maskopt ? maskopt[readfn](s.section) : null, - firstsubnet = maskval ? addrvals[0] + '/' + maskval : addrvals.filter(function(a) { return a.indexOf('/') > 0 })[0]; + addrs = L.toArray(s[readfn](s.section, 'ipaddr')), + mask = s[readfn](s.section, 'netmask'), + firstsubnet = mask ? addrs[0] + '/' + mask : addrs.filter(function(a) { return a.indexOf('/') > 0 })[0]; if (firstsubnet == null) return null; - var mask = firstsubnet.split('/')[1]; + var subnetmask = firstsubnet.split('/')[1]; - if (!isNaN(mask)) - mask = network.prefixToMask(+mask); + if (!isNaN(subnetmask)) + subnetmask = network.prefixToMask(+subnetmask); - return mask; + return subnetmask; } return view.extend({ @@ -469,6 +467,42 @@ return view.extend({ uci.unset('network', section_id, 'type'); }; + o = s.taboption('advanced', form.Value, 'ip6assign', _('IPv6 assignment length'), _('Assign a part of given length of every public IPv6-prefix to this interface')); + o.value('', _('disabled')); + o.value('64'); + o.datatype = 'max(64)'; + + o = s.taboption('advanced', form.Value, 'ip6hint', _('IPv6 assignment hint'), _('Assign prefix parts using this hexadecimal subprefix ID for this interface.')); + o.placeholder = '0'; + o.validate = function(section_id, value) { + if (value == null || value == '') + return true; + var n = parseInt(value, 16); + if (!/^(0x)?[0-9a-fA-F]+$/.test(value) || isNaN(n) || n >= 0xffffffff) + return _('Expecting a hexadecimal assignment hint'); + return true; + }; + + for (var i = 33; i <= 64; i++) + o.depends('ip6assign', String(i)); + + o = s.taboption('advanced', form.DynamicList, 'ip6addr', _('IPv6 address')); + o.datatype = 'ip6addr'; + o.placeholder = _('Add IPv6 address…'); + o.depends('ip6assign', ''); + + o = s.taboption('advanced', form.Value, 'ip6gw', _('IPv6 gateway')); + o.datatype = 'ip6addr("nomask")'; + o.depends('ip6assign', ''); + + o = s.taboption('advanced', form.Value, 'ip6prefix', _('IPv6 routed prefix'), _('Public prefix routed to this device for distribution to clients.')); + o.datatype = 'ip6addr'; + o.depends('ip6assign', ''); + + o = s.taboption('advanced', form.Value, 'ip6ifaceid', _('IPv6 suffix'), _("Optional. Allowed values: 'eui64', 'random', fixed value like '::1' or '::1:2'. When IPv6 prefix (like 'a:b:c:d::') is received from a delegating server, use the suffix (like '::1') to form the IPv6 address ('a:b:c:d::1') for the interface.")); + o.datatype = 'ip6hostid'; + o.placeholder = '::1'; + stp = s.taboption('physical', form.Flag, 'stp', _('Enable STP'), _('Enables the Spanning Tree Protocol on this bridge')); igmp = s.taboption('physical', form.Flag, 'igmp_snooping', _('Enable IGMP snooping'), _('Enables IGMP snooping on this bridge')); @@ -677,9 +711,9 @@ return view.extend({ }; so.validate = function(section_id, value) { - var node = this.map.findElement('id', this.cbid(section_id)); - if (node) - node.querySelector('input').setAttribute('placeholder', get_netmask(s, false)); + var uielem = this.getUIElement(section_id); + if (uielem) + uielem.setPlaceholder(get_netmask(s, false)); return form.Value.prototype.validate.apply(this, [ section_id, value ]); }; @@ -941,12 +975,9 @@ return view.extend({ o = s.taboption('advanced', form.Flag, 'force_link', _('Force link'), _('Set interface properties regardless of the link carrier (If set, carrier sense events do not invoke hotplug handlers).')); o.modalonly = true; - o.render = function(option_index, section_id, in_table) { - var protoopt = this.section.children.filter(function(o) { return o.option == 'proto' })[0], - protoval = protoopt ? protoopt.cfgvalue(section_id) : null; - - this.default = (protoval == 'static') ? this.enabled : this.disabled; - return this.super('render', [ option_index, section_id, in_table ]); + o.defaults = { + '1': [{ proto: 'static' }], + '0': [] }; diff --git a/luci-theme-openwrt-2020/root/etc/uci-defaults/30_luci-theme-openwrt-2020 b/luci-theme-openwrt-2020/root/etc/uci-defaults/30_luci-theme-openwrt-2020 index 7c49acfda..cd41631de 100755 --- a/luci-theme-openwrt-2020/root/etc/uci-defaults/30_luci-theme-openwrt-2020 +++ b/luci-theme-openwrt-2020/root/etc/uci-defaults/30_luci-theme-openwrt-2020 @@ -4,7 +4,6 @@ if [ "$PKG_UPGRADE" != 1 ]; then uci get luci.themes.OpenWrt2020 >/dev/null 2>&1 || \ uci batch <<-EOF set luci.themes.OpenWrt2020=/luci-static/openwrt2020 - set luci.main.mediaurlbase=/luci-static/openwrt2020 commit luci EOF fi diff --git a/macvlan/files/etc/init.d/macvlan b/macvlan/files/etc/init.d/macvlan index 01a6ee47c..b38597eff 100755 --- a/macvlan/files/etc/init.d/macvlan +++ b/macvlan/files/etc/init.d/macvlan @@ -66,7 +66,7 @@ _setup_interface() { uci -q set network.$1_dev.mtu=$(uci -q get network.$1.mtu) [ -z "$(uci -q get network.$1.masterintf)" ] && uci -q set network.$1.masterintf=$(uci -q get network.$1_dev.ifname) [ -n "$(uci -q get network.$1.masterintf)" ] && uci -q set network.$1_dev.ifname=$(uci -q get network.$1.masterintf) - [ -z "$(uci -q get network.$1.macaddr)" ] && uci -q set network.$1_dev.macaddr=$(uci -q get network.$1.macaddr) + [ -n "$(uci -q get network.$1.macaddr)" ] && uci -q set network.$1_dev.macaddr=$(uci -q get network.$1.macaddr) uci set network.$1.ifname=$1 uci -q commit network return 0 @@ -81,10 +81,12 @@ _setup_interface() { set network.$1.masterintf=$_ifname set network.$1.type=macvlan set network.$1.defaultroute=0 + delete network.$1.macaddr EOF - _macaddr=$(uci -q get "network.$1.macaddr") - _setup_macaddr "$1" "${_macaddr:-auto$(date +%s)}" + #_macaddr=$(uci -q get "network.$1.macaddr") + #_setup_macaddr "$1" "${_macaddr:-auto$(date +%s)}" + _setup_macaddr "$1" "auto$(date +%s)" uci -q set network.$1_dev.mtu=$(uci -q get network.$1.mtu) uci -q commit network } diff --git a/modemmanager/Config.in b/modemmanager/Config.in new file mode 100644 index 000000000..283a9e10a --- /dev/null +++ b/modemmanager/Config.in @@ -0,0 +1,21 @@ +menu "Configuration" +depends on PACKAGE_modemmanager + + config MODEMMANAGER_WITH_MBIM + bool "Include MBIM support" + default y + help + Compile ModemManager with MBIM support + + config MODEMMANAGER_WITH_QMI + bool "Include QMI support" + default y + help + Compile ModemManager with QMI support + + config MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS + bool "Allow AT commands via DBus" + default n + help + Compile ModemManager allowing AT commands without debug flag +endmenu diff --git a/modemmanager/Makefile b/modemmanager/Makefile new file mode 100644 index 000000000..d16b72d12 --- /dev/null +++ b/modemmanager/Makefile @@ -0,0 +1,141 @@ +# +# Copyright (C) 2016 Velocloud Inc. +# Copyright (C) 2016 Aleksander Morgado +# Copyright (C) 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter +# +# This is free software, licensed under the GNU General Public License v2. +# + +include $(TOPDIR)/rules.mk + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git +PKG_SOURCE_VERSION:=d77d8dff420dc70d6191b67e172e1df5c4e009bf +PKG_NAME:=modemmanager +PKG_VERSION:=1.16.3-$(PKG_SOURCE_VERSION) +PKG_RELEASE:=10 + +#PKG_BUILD_DIR:=$(BUILD_DIR)/modemamanager-$ + +PKG_MAINTAINER:=Nicholas Smith +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +PKG_FIXUP:=autoreconf + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/modemmanager/config + source "$(SOURCE)/Config.in" +endef + +define Package/modemmanager + SECTION:=net + CATEGORY:=Network + TITLE:=Control utility for any kind of mobile broadband modem + URL:=https://www.freedesktop.org/wiki/Software/ModemManager + DEPENDS:= \ + $(INTL_DEPENDS) \ + +glib2 \ + +dbus \ + +ppp \ + +MODEMMANAGER_WITH_MBIM:libmbim \ + +MODEMMANAGER_WITH_QMI:libqmi +endef + +define Package/modemmanager/description + ModemManager is a D-Bus-activated service which allows controlling mobile + broadband modems. Add kernel modules for your modems as needed. + Select Utilities/usb-modeswitch if needed. +endef + +CONFIGURE_ARGS += \ + --without-polkit \ + --without-udev \ + --without-systemdsystemunitdir \ + --disable-rpath \ + --disable-gtk-doc + +ifeq ($(CONFIG_MODEMMANAGER_WITH_AT_COMMAND_VIA_DBUS),y) + CONFIGURE_ARGS += --with-at-command-via-dbus +endif + +ifdef CONFIG_MODEMMANAGER_WITH_MBIM + CONFIGURE_ARGS += --with-mbim +else + CONFIGURE_ARGS += --without-mbim +endif + +ifdef CONFIG_MODEMMANAGER_WITH_QMI + CONFIGURE_ARGS += --with-qmi +else + CONFIGURE_ARGS += --without-qmi +endif + +define Build/Prepare + $(call Build/Prepare/Default) + ( cd "$(PKG_BUILD_DIR)"; \ + printf "all:\ninstall:\n" >po/Makefile.in.in; \ + ) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/include/ModemManager/*.h $(1)/usr/include/ModemManager + $(INSTALL_DIR) $(1)/usr/include/libmm-glib + $(CP) $(PKG_INSTALL_DIR)/usr/include/libmm-glib/*.h $(1)/usr/include/libmm-glib + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so* $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/ModemManager.pc $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mm-glib.pc $(1)/usr/lib/pkgconfig +endef + +define Package/modemmanager/install + $(INSTALL_DIR) $(1)/lib/udev/rules.d + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/lib/udev/rules.d/*.rules $(1)/lib/udev/rules.d + + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ModemManager $(1)/usr/sbin + + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mmcli $(1)/usr/bin + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmm-glib.so.* $(1)/usr/lib + + $(INSTALL_DIR) $(1)/usr/lib/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-shared-*.so* $(1)/usr/lib/ModemManager + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ModemManager/libmm-plugin-*.so* $(1)/usr/lib/ModemManager + + $(INSTALL_DIR) $(1)/etc/dbus-1/system.d + $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/org.freedesktop.ModemManager1.conf $(1)/etc/dbus-1/system.d + + $(INSTALL_DIR) $(1)/usr/share/dbus-1/system-services + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system-services/org.freedesktop.ModemManager1.service $(1)/usr/share/dbus-1/system-services + + $(INSTALL_DIR) $(1)/usr/share/ModemManager + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ModemManager/*.conf $(1)/usr/share/ModemManager + $(INSTALL_DATA) ./files/modemmanager.common $(1)/usr/share/ModemManager + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/modemmanager.init $(1)/etc/init.d/modemmanager + + $(INSTALL_DIR) $(1)/etc/hotplug.d/usb + $(INSTALL_DATA) ./files/25-modemmanager-usb $(1)/etc/hotplug.d/usb + + $(INSTALL_DIR) $(1)/etc/hotplug.d/net + $(INSTALL_DATA) ./files/25-modemmanager-net $(1)/etc/hotplug.d/net + + $(INSTALL_DIR) $(1)/etc/hotplug.d/tty + $(INSTALL_DATA) ./files/25-modemmanager-tty $(1)/etc/hotplug.d/tty + + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/modemmanager.proto $(1)/lib/netifd/proto/modemmanager.sh +endef + +$(eval $(call BuildPackage,modemmanager)) diff --git a/modemmanager/README.md b/modemmanager/README.md new file mode 100644 index 000000000..c9d880ea4 --- /dev/null +++ b/modemmanager/README.md @@ -0,0 +1,40 @@ +# OpenWrt ModemManager + +## Description + +Cellular modem control and connectivity + +Optional libraries libmbim and libqmi are available. +Your modem may require additional kernel modules and/or the usb-modeswitch +package. + +## Usage + +Once installed, you can configure the 2G/3G/4G modem connections directly in +/etc/config/network as in the following example: + + config interface 'broadband' + option device '/sys/devices/platform/soc/20980000.usb/usb1/1-1/1-1.2/1-1.2.1' + option proto 'modemmanager' + option apn 'ac.vodafone.es' + option allowedauth 'pap chap' + option username 'vodafone' + option password 'vodafone' + option pincode '7423' + option iptype 'ipv4' + option lowpower '1' + option signalrate '30' + +Only 'device' and 'proto' are mandatory options, the remaining ones are all +optional. + +The 'allowedauth' option allows limiting the list of authentication protocols. +It is given as a space-separated list of values, including any of the +following: 'pap', 'chap', 'mschap', 'mschapv2' or 'eap'. It will default to +allowing all protocols. + +The 'iptype' option supports any of these values: 'ipv4', 'ipv6' or 'ipv4v6'. +It will default to 'ipv4' if not given. + +The 'signalrate' option set's the signal refresh rate (in seconds) for the device. +You can call signal info with command: mmcli -m 0 --signal-get diff --git a/modemmanager/files/25-modemmanager-net b/modemmanager/files/25-modemmanager-net new file mode 100644 index 000000000..504c3d6b6 --- /dev/null +++ b/modemmanager/files/25-modemmanager-net @@ -0,0 +1,35 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +# Load common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a interface name +[ -n "${INTERFACE}" ] || exit + +[ -n "$(echo ${INTERFACE} | grep -i sqm)" ] && exit +[ -d /sys${DEVPATH} ] || exit +[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report network interface +mm_log "${ACTION} network interface ${INTERFACE}: event processed" +mm_report_event "${ACTION}" "${INTERFACE}" "net" "/sys${DEVPATH}" + +# Look for an associated cdc-wdm interface + +cdcwdm="" + +case "${ACTION}" in + "add") cdcwdm=$(mm_track_cdcwdm "${INTERFACE}") ;; + "remove") cdcwdm=$(mm_untrack_cdcwdm "${INTERFACE}") ;; +esac + +# Report cdc-wdm device, if any +[ -n "${cdcwdm}" ] && { + mm_log "${ACTION} cdc interface ${cdcwdm}: custom event processed" + mm_report_event "${ACTION}" "${cdcwdm}" "usbmisc" "/sys${DEVPATH}" +} diff --git a/modemmanager/files/25-modemmanager-tty b/modemmanager/files/25-modemmanager-tty new file mode 100644 index 000000000..1d3fb9a35 --- /dev/null +++ b/modemmanager/files/25-modemmanager-tty @@ -0,0 +1,18 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +# Load hotplug common utilities +. /usr/share/ModemManager/modemmanager.common + +# We require a device name +[ -n "$DEVNAME" ] || exit +[ -d /sys${DEVPATH} ] || exit +[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit + +# Always make sure the rundir exists +mkdir -m 0755 -p "${MODEMMANAGER_RUNDIR}" + +# Report TTY +mm_log "${ACTION} serial interface ${DEVNAME}: event processed" +mm_report_event "${ACTION}" "${DEVNAME}" "tty" "/sys${DEVPATH}" diff --git a/modemmanager/files/25-modemmanager-usb b/modemmanager/files/25-modemmanager-usb new file mode 100644 index 000000000..565b7b9c9 --- /dev/null +++ b/modemmanager/files/25-modemmanager-usb @@ -0,0 +1,15 @@ +#!/bin/sh +# Copyright (C) 2019 Aleksander Morgado + +# We need to process only full USB device removal events, we don't +# want to process specific interface removal events. +[ "$ACTION" = remove ] || exit +[ -z "${INTERFACE}" ] || exit +[ -d /sys${DEVPATH} ] || exit +[ -n "$(echo ${DEVPATH} | grep -i sqm)" ] && exit + +# Load common utilities +. /usr/share/ModemManager/modemmanager.common + +mm_clear_modem_wait_status "/sys${DEVPATH}" +mm_cleanup_interface_by_sysfspath "/sys${DEVPATH}" diff --git a/modemmanager/files/modemmanager.common b/modemmanager/files/modemmanager.common new file mode 100644 index 000000000..8de8f2946 --- /dev/null +++ b/modemmanager/files/modemmanager.common @@ -0,0 +1,336 @@ +#!/bin/sh +# Copyright (C) 2016 Velocloud Inc +# Copyright (C) 2016 Aleksander Morgado + +################################################################################ + +# If there is no interface that use modemmanager, exit +#[ -z "$(uci -q show network | grep modemmanager)" ] && exit +[ "$(uci -q get openmptcprouter.settings.modemmanager)" = "0" ] && exit + +. /lib/functions.sh +. /lib/netifd/netifd-proto.sh + +################################################################################ +# Runtime state + +MODEMMANAGER_RUNDIR="/var/run/modemmanager" +MODEMMANAGER_PID_FILE="${MODEMMANAGER_RUNDIR}/modemmanager.pid" +MODEMMANAGER_CDCWDM_CACHE="${MODEMMANAGER_RUNDIR}/cdcwdm.cache" +MODEMMANAGER_SYSFS_CACHE="${MODEMMANAGER_RUNDIR}/sysfs.cache" +MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache" + +################################################################################ +# Common logging + +mm_log() { + logger -t "ModemManager" "hotplug: $*" +} + +################################################################################ +# Receives as input argument the full sysfs path of the device +# Returns the physical device sysfs path +# +# NOTE: this method only works when the device exists, i.e. it cannot be used +# on removal hotplug events + +mm_find_physdev_sysfs_path() { + local tmp_path="$1" + + while true; do + tmp_path=$(dirname "${tmp_path}") + + # avoid infinite loops iterating + [ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return + + # the physical device will be that with a idVendor and idProduct pair of files + [ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && { + tmp_path=$(readlink -f "$tmp_path") + echo "${tmp_path}" + return + } + done +} + +################################################################################ + +# Returns the cdc-wdm name retrieved from sysfs +mm_track_cdcwdm() { + local wwan="$1" + local cdcwdm + + cdcwdm=$(ls "/sys/class/net/${wwan}/device/usbmisc/") + [ -n "${cdcwdm}" ] || return + + # We have to cache it for later, as we won't be able to get the + # associated cdc-wdm device on a remove event + echo "${wwan} ${cdcwdm}" >> "${MODEMMANAGER_CDCWDM_CACHE}" + + echo "${cdcwdm}" +} + +# Returns the cdc-wdm name retrieved from the cache +mm_untrack_cdcwdm() { + local wwan="$1" + local cdcwdm + + # Look for the cached associated cdc-wdm device + [ -f "${MODEMMANAGER_CDCWDM_CACHE}" ] || return + + cdcwdm=$(awk -v wwan="${wwan}" '!/^#/ && $0 ~ wwan { print $2 }' "${MODEMMANAGER_CDCWDM_CACHE}") + [ -n "${cdcwdm}" ] || return + + # Remove from cache + sed -i "/${wwan} ${cdcwdm}/d" "${MODEMMANAGER_CDCWDM_CACHE}" + + echo "${cdcwdm}" +} + +################################################################################ +# ModemManager needs some time from the ports being added until a modem object +# is exposed in DBus. With the logic here we do an explicit wait of N seconds +# for ModemManager to expose the new modem object, making sure that the wait is +# unique per device (i.e. per physical device sysfs path). + +# Gets the modem wait status as retrieved from the cache +mm_get_modem_wait_status() { + local sysfspath="$1" + + # If no sysfs cache file, we're done + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] || return + + # Get status of the sysfs path + awk -v sysfspath="${sysfspath}" '!/^#/ && $0 ~ sysfspath { print $2 }' "${MODEMMANAGER_SYSFS_CACHE}" +} + +# Clear the modem wait status from the cache, if any +mm_clear_modem_wait_status() { + local sysfspath="$1" + + local escaped_sysfspath + + [ -f "${MODEMMANAGER_SYSFS_CACHE}" ] && { + # escape '/', '\' and '&' for sed... + escaped_sysfspath=$(echo "$sysfspath" | sed -e 's/[\/&]/\\&/g') + sed -i "/${escaped_sysfspath}/d" "${MODEMMANAGER_SYSFS_CACHE}" + } +} + +# Sets the modem wait status in the cache +mm_set_modem_wait_status() { + local sysfspath="$1" + local status="$2" + + # Remove sysfs line before adding the new one with the new state + mm_clear_modem_wait_status "${sysfspath}" + + # Add the new status + echo "${sysfspath} ${status}" >> "${MODEMMANAGER_SYSFS_CACHE}" +} + +# Callback for config_foreach() +mm_get_modem_config_foreach_cb() { + local cfg="$1" + local sysfspath="$2" + + local proto + config_get proto "${cfg}" proto + [ "${proto}" = modemmanager ] || return 0 + + local dev + dev=$(uci_get network "${cfg}" device) + [ "${dev}" = "${sysfspath}" ] || return 0 + + echo "${cfg}" +} + +# Returns the name of the interface configured for this device +mm_get_modem_config() { + local sysfspath="$1" + + # Look for configuration for the given sysfs path + config_load network + config_foreach mm_get_modem_config_foreach_cb interface "${sysfspath}" +} + +# Wait for a modem in the specified sysfspath +mm_wait_for_modem() { + local cfg="$1" + local sysfspath="$2" + + # TODO: config max wait + local n=45 + local step=5 + + while [ $n -ge 0 ]; do + [ -d "${sysfspath}" ] || { + mm_log "error: ignoring modem detection request: no device at ${sysfspath}" + proto_set_available "${cfg}" 0 + return 1 + } + + # Check if the modem exists at the given sysfs path + if ! mmcli -m "${sysfspath}" > /dev/null 2>&1 + then + mm_log "error: modem not detected at sysfs path" + else + mm_log "modem exported successfully at ${sysfspath}" + mm_log "setting interface '${cfg}' as available" + proto_set_available "${cfg}" 1 + return 0 + fi + + sleep $step + n=$((n-step)) + done + + mm_log "error: timed out waiting for the modem to get exported at ${sysfspath}" + proto_set_available "${cfg}" 0 + return 2 +} + +mm_report_modem_wait() { + local sysfspath=$1 + + local parent_sysfspath status + + parent_sysfspath=$(mm_find_physdev_sysfs_path "$sysfspath") + [ -n "${parent_sysfspath}" ] || { + mm_log "error: parent device sysfspath not found" + return + } + + status=$(mm_get_modem_wait_status "${parent_sysfspath}") + case "${status}" in + "") + local cfg + + cfg=$(mm_get_modem_config "${parent_sysfspath}") + if [ -n "${cfg}" ]; then + mm_log "interface '${cfg}' is set to configure device '${parent_sysfspath}'" + mm_log "now waiting for modem at sysfs path ${parent_sysfspath}" + mm_set_modem_wait_status "${parent_sysfspath}" "processed" + # Launch subshell for the explicit wait + ( mm_wait_for_modem "${cfg}" "${parent_sysfspath}" ) > /dev/null 2>&1 & + else + mm_log "no need to wait for modem at sysfs path ${parent_sysfspath}" + mm_set_modem_wait_status "${parent_sysfspath}" "ignored" + fi + ;; + "processed") + mm_log "already waiting for modem at sysfs path ${parent_sysfspath}" + ;; + "ignored") + ;; + *) + mm_log "error: unknown status read for device at sysfs path ${parent_sysfspath}" + ;; + esac +} + +################################################################################ +# Cleanup interfaces + +mm_cleanup_interface_cb() { + local cfg="$1" + + local proto + config_get proto "${cfg}" proto + [ "${proto}" = modemmanager ] || return 0 + + proto_set_available "${cfg}" 0 +} + +mm_cleanup_interfaces() { + config_load network + config_foreach mm_cleanup_interface_cb interface +} + +mm_cleanup_interface_by_sysfspath() { + local dev="$1" + + local cfg + cfg=$(mm_get_modem_config "$dev") + [ -n "${cfg}" ] || return + + mm_log "setting interface '$cfg' as unavailable" + proto_set_available "${cfg}" 0 +} + +################################################################################ +# Event reporting + +# Receives as input the action, the device name and the subsystem +mm_report_event() { + local action="$1" + local name="$2" + local subsystem="$3" + local sysfspath="$4" + + # Track/untrack events in cache + case "${action}" in + "add") + # On add events, store event details in cache (if not exists yet) + grep -qs "${name},${subsystem}" "${MODEMMANAGER_EVENTS_CACHE}" || \ + echo "${action},${name},${subsystem},${sysfspath}" >> "${MODEMMANAGER_EVENTS_CACHE}" + ;; + "remove") + # On remove events, remove old events from cache (match by subsystem+name) + sed -i "/${name},${subsystem}/d" "${MODEMMANAGER_EVENTS_CACHE}" + ;; + esac + + # Report the event + mm_log "event reported: action=${action}, name=${name}, subsystem=${subsystem}" + mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 1>/dev/null 2>&1 & + + # Wait for added modem if a sysfspath is given + [ -n "${sysfspath}" ] && [ "$action" = "add" ] && mm_report_modem_wait "${sysfspath}" +} + +mm_report_event_from_cache_line() { + local event_line="$1" + + local action name subsystem sysfspath + action=$(echo "${event_line}" | awk -F ',' '{ print $1 }') + name=$(echo "${event_line}" | awk -F ',' '{ print $2 }') + subsystem=$(echo "${event_line}" | awk -F ',' '{ print $3 }') + sysfspath=$(echo "${event_line}" | awk -F ',' '{ print $4 }') + + mm_log "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}" + mm_report_event "${action}" "${name}" "${subsystem}" "${sysfspath}" +} + +mm_report_events_from_cache() { + # Remove the sysfs cache + rm -f "${MODEMMANAGER_SYSFS_CACHE}" + + local n=60 + local step=1 + local mmrunning=0 + + # Wait for ModemManager to be available in the bus + while [ $n -ge 0 ]; do + sleep $step + mm_log "checking if ModemManager is available..." + + if ! mmcli -L >/dev/null 2>&1 + then + mm_log "ModemManager not yet available" + else + mmrunning=1 + break + fi + n=$((n-step)) + done + + [ ${mmrunning} -eq 1 ] || { + mm_log "error: couldn't report initial kernel events: ModemManager not running" + return + } + + # Report cached kernel events + while IFS= read -r event_line; do + mm_report_event_from_cache_line "${event_line}" + done < ${MODEMMANAGER_EVENTS_CACHE} +} diff --git a/modemmanager/files/modemmanager.init b/modemmanager/files/modemmanager.init new file mode 100755 index 000000000..b3f9f9290 --- /dev/null +++ b/modemmanager/files/modemmanager.init @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2016 Aleksander Morgado + +USE_PROCD=1 +START=70 + +stop_service() { + # Load common utils + . /usr/share/ModemManager/modemmanager.common + # Set all configured interfaces as unavailable + mm_cleanup_interfaces +} + +start_service() { + # Setup ModemManager service + # + # We will make sure that the rundir always exists, and we initially cleanup + # all interfaces flagging them as unavailable. + # + # The cached events processing will wait for MM to be available in DBus + # and will make sure all ports are re-notified to ModemManager every time + # it starts. + # + # All these commands need to be executed on every MM start, even after + # procd-triggered respawns, which is why they're all included as instance command + # + procd_open_instance + procd_set_param command sh -c ". /usr/share/ModemManager/modemmanager.common; \ + mkdir -m 0755 -p ${MODEMMANAGER_RUNDIR}; \ + mm_cleanup_interfaces; \ + ( mm_report_events_from_cache ) >/dev/null 2>&1 & \ + /usr/sbin/ModemManager" + procd_set_param respawn "${respawn_threshold:-3600}" "${respawn_timeout:-5}" "${respawn_retry:-5}" + procd_set_param pidfile "${MODEMMANAGER_PID_FILE}" + procd_close_instance +} diff --git a/modemmanager/files/modemmanager.proto b/modemmanager/files/modemmanager.proto new file mode 100755 index 000000000..d24910b98 --- /dev/null +++ b/modemmanager/files/modemmanager.proto @@ -0,0 +1,550 @@ +#!/bin/sh +# Copyright (C) 2016-2019 Aleksander Morgado + +[ -x /usr/bin/mmcli ] || exit 0 +[ -x /usr/sbin/pppd ] || exit 0 + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + . ./ppp.sh + init_proto "$@" +} + +cdr2mask () +{ + # Number of args to shift, 255..255, first non-255 byte, zeroes + set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0 + if [ "$1" -gt 1 ] + then + shift "$1" + else + shift + fi + echo "${1-0}"."${2-0}"."${3-0}"."${4-0}" +} + +# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue +# The second argument must be exactly the name of the field to read +# +# Sample output: +# $ mmcli -m 0 -K +# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0 +# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752 +# modem.generic.manufacturer : Dell Inc. +# modem.generic.model : DW5821e Snapdragon X20 LTE +# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026 +# modem.generic.carrier-configuration : GCF +# modem.generic.carrier-configuration-revision : 08E00009 +# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE +# .... +modemmanager_get_field() { + local list=$1 + local field=$2 + local value="" + + [ -z "${list}" ] || [ -z "${field}" ] && return + + # there is always at least a whitespace after each key, and we use that as part of the + # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result + # when grepping for 'modem.generic.state'. + line=$(echo "${list}" | grep "${field} ") + value=$(echo ${line#*:}) + + # not found? + [ -n "${value}" ] || return 2 + + # only print value if set + [ "${value}" != "--" ] && echo "${value}" + return 0 +} + +# build a comma-separated list of values from the list +modemmanager_get_multivalue_field() { + local list=$1 + local field=$2 + local value="" + local length idx item + + [ -z "${list}" ] || [ -z "${field}" ] && return + + length=$(modemmanager_get_field "${list}" "${field}.length") + [ -n "${length}" ] || return 0 + [ "$length" -ge 1 ] || return 0 + + idx=1 + while [ $idx -le "$length" ]; do + item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]") + [ -n "${item}" ] && [ "${item}" != "--" ] && { + [ -n "${value}" ] && value="${value}, " + value="${value}${item}" + } + idx=$((idx + 1)) + done + + # nothing built? + [ -n "${value}" ] || return 2 + + # only print value if set + echo "${value}" + return 0 +} + +modemmanager_cleanup_connection() { + local modemstatus="$1" + + local bearercount idx bearerpath + + bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") + + # do nothing if no bearers reported + [ -n "${bearercount}" ] && [ "$bearercount" -ge 1 ] && { + # explicitly disconnect just in case + mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1 + # and remove all bearer objects, if any found + idx=1 + while [ $idx -le "$bearercount" ]; do + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[$idx\]") + mmcli --modem "${device}" --delete-bearer="${bearerpath}" >/dev/null 2>&1 + idx=$((idx + 1)) + done + } +} + +modemmanager_connected_method_ppp_ipv4() { + local interface="$1" + local ttyname="$2" + local username="$3" + local password="$4" + local allowedauth="$5" + + # all auth types are allowed unless a user given list is given + local authopts + local pap=1 + local chap=1 + local mschap=1 + local mschapv2=1 + local eap=1 + + [ -n "$allowedauth" ] && { + pap=0 chap=0 mschap=0 mschapv2=0 eap=0 + for auth in $allowedauth; do + case $auth in + "pap") pap=1 ;; + "chap") chap=1 ;; + "mschap") mschap=1 ;; + "mschapv2") mschapv2=1 ;; + "eap") eap=1 ;; + *) ;; + esac + done + } + + [ $pap -eq 1 ] || append authopts "refuse-pap" + [ $chap -eq 1 ] || append authopts "refuse-chap" + [ $mschap -eq 1 ] || append authopts "refuse-mschap" + [ $mschapv2 -eq 1 ] || append authopts "refuse-mschap-v2" + [ $eap -eq 1 ] || append authopts "refuse-eap" + + proto_run_command "${interface}" /usr/sbin/pppd \ + "${ttyname}" \ + 115200 \ + nodetach \ + noaccomp \ + nobsdcomp \ + nopcomp \ + novj \ + noauth \ + $authopts \ + ${username:+ user $username} \ + ${password:+ password $password} \ + lcp-echo-failure 5 \ + lcp-echo-interval 15 \ + lock \ + crtscts \ + nodefaultroute \ + usepeerdns \ + ipparam "${interface}" \ + ip-up-script /lib/netifd/ppp-up \ + ip-down-script /lib/netifd/ppp-down +} + +modemmanager_disconnected_method_ppp_ipv4() { + local interface="$1" + + echo "running disconnection (ppp method)" + + [ -n "${ERROR}" ] && { + local errorstring + errorstring=$(ppp_exitcode_tostring "${ERROR}") + case "$ERROR" in + 0) + ;; + 2) + proto_notify_error "$interface" "$errorstring" + proto_block_restart "$interface" + ;; + *) + proto_notify_error "$interface" "$errorstring" + ;; + esac + } || echo "pppd result code not given" + + proto_kill_command "$interface" +} + +modemmanager_connected_method_dhcp_ipv4() { + local interface="$1" + local wwan="$2" + local metric="$3" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + proto_send_update "${interface}" + + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@${interface}" + json_add_string proto "dhcp" + proto_add_dynamic_defaults + [ -n "$metric" ] && json_add_int metric "${metric}" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +modemmanager_connected_method_static_ipv4() { + local interface="$1" + local wwan="$2" + local address="$3" + local prefix="$4" + local gateway="$5" + local mtu="$6" + local dns1="$7" + local dns2="$8" + local metric="$9" + + local mask="" + + [ -n "${address}" ] || { + proto_notify_error "${interface}" ADDRESS_MISSING + return + } + + [ -n "${prefix}" ] || { + proto_notify_error "${interface}" PREFIX_MISSING + return + } + mask=$(cdr2mask "${prefix}") + + [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + echo "adding IPv4 address ${address}, netmask ${mask}" + proto_add_ipv4_address "${address}" "${mask}" + [ -n "${gateway}" ] && { + echo "adding default IPv4 route via ${gateway}" + proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}" + } + [ -n "${dns1}" ] && { + echo "adding primary DNS at ${dns1}" + proto_add_dns_server "${dns1}" + } + [ -n "${dns2}" ] && { + echo "adding secondary DNS at ${dns2}" + proto_add_dns_server "${dns2}" + } + [ -n "$metric" ] && json_add_int metric "${metric}" + proto_send_update "${interface}" +} + +modemmanager_connected_method_dhcp_ipv6() { + local interface="$1" + local wwan="$2" + local metric="$3" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + proto_send_update "${interface}" + + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@${interface}" + json_add_string proto "dhcpv6" + proto_add_dynamic_defaults + json_add_string extendprefix 1 # RFC 7278: Extend an IPv6 /64 Prefix to LAN + [ -n "$metric" ] && json_add_int metric "${metric}" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +modemmanager_connected_method_static_ipv6() { + local interface="$1" + local wwan="$2" + local address="$3" + local prefix="$4" + local gateway="$5" + local mtu="$6" + local dns1="$7" + local dns2="$8" + local metric="$9" + + [ -n "${address}" ] || { + proto_notify_error "${interface}" ADDRESS_MISSING + return + } + + [ -n "${prefix}" ] || { + proto_notify_error "${interface}" PREFIX_MISSING + return + } + + [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}" + + proto_init_update "${wwan}" 1 + proto_set_keep 1 + echo "adding IPv6 address ${address}, prefix ${prefix}" + proto_add_ipv6_address "${address}" "128" + proto_add_ipv6_prefix "${address}/${prefix}" + [ -n "${gateway}" ] && { + echo "adding default IPv6 route via ${gateway}" + proto_add_ipv6_route "${gateway}" "128" + proto_add_ipv6_route "::0" "0" "${gateway}" "" "" "${address}/${prefix}" + } + [ -n "${dns1}" ] && { + echo "adding primary DNS at ${dns1}" + proto_add_dns_server "${dns1}" + } + [ -n "${dns2}" ] && { + echo "adding secondary DNS at ${dns2}" + proto_add_dns_server "${dns2}" + } + [ -n "$metric" ] && json_add_int metric "${metric}" + proto_send_update "${interface}" +} + +modemmanager_disconnected_method_common() { + local interface="$1" + + echo "running disconnection (common)" + proto_notify_error "${interface}" MM_DISCONNECT_IN_PROGRESS + + proto_init_update "*" 0 + proto_send_update "${interface}" +} + +proto_modemmanager_init_config() { + available=1 + no_device=1 + proto_config_add_string device + proto_config_add_string apn + proto_config_add_string 'allowedauth:list(string)' + proto_config_add_string username + proto_config_add_string password + proto_config_add_string pincode + proto_config_add_string iptype + proto_config_add_int signalrate + proto_config_add_boolean lowpower + proto_config_add_defaults +} + +proto_modemmanager_setup() { + local interface="$1" + + local modempath modemstatus bearercount bearerpath connectargs bearerstatus beareriface + local bearermethod_ipv4 bearermethod_ipv6 auth cliauth + local operatorname operatorid registration accesstech signalquality + + local device apn allowedauth username password pincode iptype metric signalrate + + local address prefix gateway mtu dns1 dns2 + + json_get_vars device apn allowedauth username password pincode iptype metric signalrate + + # validate sysfs path given in config + [ -n "${device}" ] || { + echo "No device specified" + proto_notify_error "${interface}" NO_DEVICE + proto_set_available "${interface}" 0 + return 1 + } + [ -e "${device}" ] || { + echo "Device not found in sysfs" + proto_set_available "${interface}" 0 + return 1 + } + + # validate that ModemManager is handling the modem at the sysfs path + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + modempath=$(modemmanager_get_field "${modemstatus}" "modem.dbus-path") + [ -n "${modempath}" ] || { + echo "Device not managed by ModemManager" + proto_notify_error "${interface}" DEVICE_NOT_MANAGED + proto_set_available "${interface}" 0 + return 1 + } + echo "modem available at ${modempath}" + + # always cleanup before attempting a new connection, just in case + modemmanager_cleanup_connection "${modemstatus}" + + # if allowedauth list given, build option string + for auth in $allowedauth; do + cliauth="${cliauth}${cliauth:+|}$auth" + done + + # setup connect args; APN mandatory (even if it may be empty) + echo "starting connection with apn '${apn}'..." + proto_notify_error "${interface}" MM_CONNECT_IN_PROGRESS + + connectargs="apn=${apn}${iptype:+,ip-type=${iptype}}${cliauth:+,allowed-auth=${cliauth}}${username:+,user=${username}}${password:+,password=${password}}${pincode:+,pin=${pincode}}" + mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || { + proto_notify_error "${interface}" MM_CONNECT_FAILED + proto_block_restart "${interface}" + return 1 + } + + # check if Signal refresh rate is set + if [ -n "${signalrate}" ] && [ "${signalrate}" -eq "${signalrate}" ] 2>/dev/null; then + echo "setting signal refresh rate to ${signalrate} seconds" + mmcli --modem="${device}" --signal-setup="${signalrate}" + else + echo "signal refresh rate is not set" + fi + + # log additional useful information + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + operatorname=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-name") + [ -n "${operatorname}" ] && echo "network operator name: ${operatorname}" + operatorid=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-code") + [ -n "${operatorid}" ] && echo "network operator MCCMNC: ${operatorid}" + registration=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.registration-state") + [ -n "${registration}" ] && echo "registration type: ${registration}" + accesstech=$(modemmanager_get_multivalue_field "${modemstatus}" "modem.generic.access-technologies") + [ -n "${accesstech}" ] && echo "access technology: ${accesstech}" + signalquality=$(modemmanager_get_field "${modemstatus}" "modem.generic.signal-quality.value") + [ -n "${signalquality}" ] && echo "signal quality: ${signalquality}%" + + # we won't like it if there are more than one bearers, as that would mean the + # user manually created them, and that's unsupported by this proto + bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length") + [ -n "${bearercount}" ] && [ "$bearercount" -eq 1 ] || { + proto_notify_error "${interface}" INVALID_BEARER_LIST + return 1 + } + + # load connected bearer information + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") + bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) + + # load network interface and method information + beareriface=$(modemmanager_get_field "${bearerstatus}" "bearer.status.interface") + bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") + bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") + + # setup IPv4 + [ -n "${bearermethod_ipv4}" ] && { + echo "IPv4 connection setup required in interface ${interface}: ${bearermethod_ipv4}" + case "${bearermethod_ipv4}" in + "dhcp") + modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}" + ;; + "static") + address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.address") + prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.prefix") + gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.gateway") + mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.mtu") + dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[1\]") + dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[2\]") + modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" + ;; + "ppp") + modemmanager_connected_method_ppp_ipv4 "${interface}" "${beareriface}" "${username}" "${password}" "${allowedauth}" + ;; + *) + proto_notify_error "${interface}" UNKNOWN_METHOD + return 1 + ;; + esac + } + + # setup IPv6 + # note: if using ipv4v6, both IPv4 and IPv6 settings will have the same MTU and metric values reported + [ -n "${bearermethod_ipv6}" ] && { + echo "IPv6 connection setup required in interface ${interface}: ${bearermethod_ipv6}" + case "${bearermethod_ipv6}" in + "dhcp") + modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}" + ;; + "static") + address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.address") + prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.prefix") + gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.gateway") + mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.mtu") + dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[1\]") + dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[2\]") + modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}" + ;; + "ppp") + proto_notify_error "${interface}" "unsupported method" + return 1 + ;; + *) + proto_notify_error "${interface}" UNKNOWN_METHOD + return 1 + ;; + esac + } + + return 0 +} + +proto_modemmanager_teardown() { + local interface="$1" + + local modemstatus bearerpath errorstring + local bearermethod_ipv4 bearermethod_ipv6 + + local device lowpower iptype + json_get_vars device lowpower iptype + + echo "stopping network" + proto_notify_error "${interface}" MM_TEARDOWN_IN_PROGRESS + + # load connected bearer information, just the first one should be ok + modemstatus=$(mmcli --modem="${device}" --output-keyvalue) + bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]") + [ -n "${bearerpath}" ] || { + echo "couldn't load bearer path" + return + } + + # load bearer connection methods + bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue) + bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method") + [ -n "${bearermethod_ipv4}" ] && + echo "IPv4 connection teardown required in interface ${interface}: ${bearermethod_ipv4}" + bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method") + [ -n "${bearermethod_ipv6}" ] && + echo "IPv6 connection teardown required in interface ${interface}: ${bearermethod_ipv6}" + + # disconnection handling only requires special treatment in IPv4/PPP + [ "${bearermethod_ipv4}" = "ppp" ] && modemmanager_disconnected_method_ppp_ipv4 "${interface}" + modemmanager_disconnected_method_common "${interface}" + + # disconnect + mmcli --modem="${device}" --simple-disconnect || + proto_notify_error "${interface}" DISCONNECT_FAILED + + # disable + mmcli --modem="${device}" --disable + proto_notify_error "${interface}" MM_MODEM_DISABLED + + # low power, only if requested + [ "${lowpower:-0}" -lt 1 ] || + mmcli --modem="${device}" --set-power-state-low +} + +[ -n "$INCLUDE_ONLY" ] || { + add_protocol modemmanager +} diff --git a/mptcp/files/etc/init.d/mptcp b/mptcp/files/etc/init.d/mptcp index 059da16aa..334cc0632 100755 --- a/mptcp/files/etc/init.d/mptcp +++ b/mptcp/files/etc/init.d/mptcp @@ -10,7 +10,7 @@ USE_PROCD=1 . /lib/functions/network.sh global_multipath_settings() { - local multipath mptcp_path_manager mptcp_schdeduler mptcp_debug congestion mptcp_checksum mptcp_syn_retries mptcp_fullmesh_num_subflows mptcp_fullmesh_create_on_err mptcp_ndiffports_num_subflows + local multipath mptcp_path_manager mptcp_schdeduler mptcp_debug congestion mptcp_checksum mptcp_syn_retries mptcp_fullmesh_num_subflows mptcp_fullmesh_create_on_err mptcp_ndiffports_num_subflows mptcp_rr_cwnd_limited mptcp_rr_num_segments local multipath_status=0 config_load network config_get multipath globals multipath @@ -23,6 +23,8 @@ global_multipath_settings() { config_get mptcp_fullmesh_num_subflows globals mptcp_fullmesh_num_subflows config_get mptcp_fullmesh_create_on_err globals mptcp_fullmesh_create_on_err config_get mptcp_ndiffports_num_subflows globals mptcp_ndiffports_num_subflows + config_get mptcp_rr_cwnd_limited globals mptcp_rr_cwnd_limited + config_get mptcp_rr_num_segments globals mptcp_rr_num_segments [ "$multipath" = "enable" ] && multipath_status=1 @@ -37,6 +39,8 @@ global_multipath_settings() { [ -z "$mptcp_fullmesh_num_subflows" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/num_subflows="$mptcp_fullmesh_num_subflows" [ -z "$mptcp_fullmesh_create_on_err" ] || sysctl -qw /sys/module/mptcp_fullmesh/parameters/create_on_err="$mptcp_fullmesh_create_on_err" [ -z "$mptcp_ndiffports_num_subflows" ] || sysctl -qw /sys/module/mptcp_ndiffports/parameters/num_subflows="$mptcp_ndiffports_num_subflows" + [ -z "$mptcp_rr_cwnd_limited" ] || sysctl -qw /sys/module/mptcp_rr/parameters/cwnd_limited="$mptcp_rr_cwnd_limited" + [ -z "$mptcp_rr_num_segments" ] || sysctl -qw /sys/module/mptcp_rr/parameters/num_segments="$mptcp_rr_num_segments" } interface_macaddr_count() { @@ -112,6 +116,7 @@ interface_multipath_settings() { [ "$mode" != "off" ] && { [ -n "$mptcpintf" ] && mptcpintf="$mptcpintf $iface" [ -z "$mptcpintf" ] && mptcpintf="$iface" + [ -z "$mptcpmintf" ] && mptcpmintf="$config" uci -q set network.${config}.defaultroute=0 uci -q set network.${config}.peerdns=0 } @@ -238,7 +243,7 @@ interface_multipath_settings() { EOF else #echo "Add routes for $ipaddr table $id" - ip rule add from $ipaddr table $id pref 0 + [ -n "$ipaddr" ] && ip rule add from $ipaddr table $id pref 0 ip route replace $network/$netmask dev $iface scope link metric $id 2>&1 >/dev/null ip route replace $network/$netmask dev $iface scope link table $id 2>&1 >/dev/null ip route replace default via $gateway dev $iface table $id 2>&1 >/dev/null @@ -384,9 +389,9 @@ add_route() { config_get interface "$1" interface iface=$(ifstatus "$interface" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$interface" | jsonfilter -q -e '@["device"]') - routeset="$routeset dev $iface" + [ -n "$iface" ] && routeset="$routeset dev $iface" logger -t "MPTCP" "Add route $routeset" - ip route replace $routeset 2>&1 >/dev/null + [ -n "$routeset" ] && ip route replace $routeset 2>&1 >/dev/null } add_route6() { @@ -405,9 +410,9 @@ add_route6() { config_get interface "$1" interface iface=$(ifstatus "$interface" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $iface | grep '@')" ] && iface=$(ifstatus "$interface" | jsonfilter -q -e '@["device"]') - routeset="$routeset dev $iface" + [ -n "$iface" ] && routeset="$routeset dev $iface" logger -t "MPTCP" "Add IPv6 route $routeset" - ip -6 route replace $routeset 2>&1 >/dev/null + [ -n "$routeset" ] && ip -6 route replace $routeset 2>&1 >/dev/null } remove() { @@ -431,6 +436,7 @@ start_service() { } mptcpintf="" + mptcpmintf="" master="" count="0" config_load openmptcprouter @@ -455,7 +461,7 @@ start_service() { config_foreach add_route route6 # If no master is defined, one interface is defined as master if [ "$master" = "" ] && [ "$intf" = "" ]; then - intfmaster="$(echo $mptcpintf | cut -d' ' -f1 | tr -d '\n')" + intfmaster="$mptcpmintf" [ "$intfmaster" != "" ] && { logger -t "MPTCP" "No master multipath defined, setting it to $intfmaster" uci -q set network.${intfmaster}.multipath="master" diff --git a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking index 64bda2481..5659e806e 100755 --- a/mptcp/files/usr/share/omr/post-tracking.d/post-tracking +++ b/mptcp/files/usr/share/omr/post-tracking.d/post-tracking @@ -8,7 +8,10 @@ set_route() { [ -z "$SETDEFAULT" ] && SETDEFAULT="yes" multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" + } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') @@ -42,7 +45,10 @@ set_route6() { [ -z "$SETDEFAULT" ] && SETDEFAULT="yes" multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" + } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') @@ -78,8 +84,11 @@ set_server_default_route() { [ "$disabled" = "1" ] && return multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ]; then + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + } + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route via $OMR_TRACKER_DEVICE_GATEWAY" if [ "$(ip r show $serverip | grep nexthop)" != "" ]; then ip r delete $serverip >/dev/null 2>&1 @@ -100,8 +109,11 @@ set_server_default_route6() { [ "$disabled" = "1" ] && return multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ]; then + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + } + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric 1 | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) default route via $OMR_TRACKER_DEVICE_GATEWAY6" if [ "$(ip -6 r show $serverip | grep nexthop)" != "" ]; then ip -6 r delete $serverip >/dev/null 2>&1 @@ -147,7 +159,10 @@ set_routes_intf() { local INTERFACE=$1 multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo 'off')" + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" + } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) @@ -155,7 +170,8 @@ set_routes_intf() { interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') #multipath_current_config=$(multipath $interface_if | grep 'deactivated') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") - if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_if" != "" ] && [ "$interface_up" = "true" ]; then + interface_vpn=$(uci -q get openmptcprouter.$INTERFACE.vpn || echo "0") + if ([ "$interface_vpn" = "0" ] || [ "$(uci -q get openmptcprouter.settings.allmptcpovervpn)" = "0" ]) && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_if" != "" ] && [ "$interface_up" = "true" ]; then interface_gw="$(uci -q get network.$INTERFACE.gateway)" if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") @@ -166,7 +182,7 @@ set_routes_intf() { if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.${INTERFACE}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") fi - #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ "$(ip route show $serverip | grep $interface_if)" = "" ]; then + #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$serverip" ] && [ "$(ip route show $serverip | grep $interface_if)" = "" ]; then if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -z "$(echo $interface_gw | grep :)" ]; then if [ "$multipath_config_route" = "master" ]; then weight=10 @@ -197,7 +213,10 @@ set_routes_intf6() { local INTERFACE=$1 multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo 'off')" + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" + } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) @@ -205,7 +224,8 @@ set_routes_intf6() { interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') #multipath_current_config=$(multipath $interface_if | grep 'deactivated') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") - if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_if" != "" ] && [ "$interface_up" = "true" ]; then + interface_vpn=$(uci -q get openmptcprouter.$INTERFACE.vpn || echo "0") + if ([ "$interface_vpn" = "0" ] || [ "$(uci -q get openmptcprouter.settings.allmptcpovervpn)" = "0" ]) && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_if" != "" ] && [ "$interface_up" = "true" ]; then interface_gw="$(uci -q get network.$INTERFACE.ip6gw)" interface_ip6="$(uci -q get network.$INTERFACE.ip6)" if [ -z "$interface_gw" ]; then @@ -232,7 +252,7 @@ set_routes_intf6() { if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.${INTERFACE}_6 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="::"].nexthop' | tr -d "\n") fi - #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ "$(ip -6 route show $serverip | grep $interface_if)" = "" ]; then + #if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$serverip" ] && [ "$(ip -6 route show $serverip | grep $interface_if)" = "" ]; then if [ "$interface_gw" != "" ] && [ "$interface_if" != "" ] && [ -n "$(echo $interface_gw | grep :)" ]; then if [ "$multipath_config_route" = "master" ]; then weight=10 @@ -263,14 +283,18 @@ set_route_balancing() { INTERFACE=$1 multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo 'off')" + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" + } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") - if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + interface_vpn=$(uci -q get openmptcprouter.$INTERFACE.vpn || echo "0") + if ([ "$interface_vpn" = "0" ] || [ "$(uci -q get openmptcprouter.settings.allmptcpovervpn)" = "0" ]) && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then interface_gw="$(uci -q get network.$INTERFACE.gateway)" if [ -z "$interface_gw" ]; then interface_gw=$(ubus call network.interface.$INTERFACE status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n") @@ -307,14 +331,18 @@ set_route_balancing6() { INTERFACE=$1 multipath_config_route=$(uci -q get openmptcprouter.$INTERFACE.multipath) [ -z "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo 'off')" + [ "$(uci -q get openmptcprouter.$INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${INTERFACE}.multipath || echo "off")" + } interface_if=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(uci -q get network.$INTERFACE.ifname) [ -n "$(echo $interface_if | grep '@')" ] && interface_if=$(ifstatus "$INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') interface_current_config=$(uci -q get openmptcprouter.$INTERFACE.state || echo "up") - if [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + interface_vpn=$(uci -q get openmptcprouter.$INTERFACE.vpn || echo "0") + if ([ "$interface_vpn" = "0" ] || [ "$(uci -q get openmptcprouter.settings.allmptcpovervpn)" = "0" ]) && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then interface_gw="$(uci -q get network.$INTERFACE.gateway)" interface_ip6="$(uci -q get network.$INTERFACE.ip6)" if [ -z "$interface_gw" ]; then @@ -377,7 +405,10 @@ set_server_all_routes() { interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + } if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_up" = "true" ]; then routesintf="" routesintfbackup="" @@ -418,8 +449,10 @@ set_server_all_routes6() { [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]') interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["up"]') multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo 'off') - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + } if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_up" = "true" ]; then routesintf="" routesintfbackup="" @@ -460,7 +493,10 @@ set_server_route() { [ -z "$metric" ] && metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + } interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') @@ -469,13 +505,13 @@ set_server_route() { #multipath_current_config=$(multipath $interface_if | grep "deactivated") interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") #if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$multipath_current_config" = "" ]; then - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + if [ "$serverip" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) route via $OMR_TRACKER_DEVICE_GATEWAY metric $metric" ip route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric 2>&1 >/dev/null fi } config_list_foreach $server ip server_route - if [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + if [ -n "$metric" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $metric 2>&1 >/dev/null fi } @@ -492,7 +528,10 @@ set_server_route6() { [ -z "$metric" ] && metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) multipath_config_route=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipath) [ "$multipath_config_route" ] && multipath_config_route=$(uci -q get network.$OMR_TRACKER_INTERFACE.multipath || echo "off") - [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + } interface_if=$(uci -q get network.$OMR_TRACKER_INTERFACE.ifname) [ -z "$interface_if" ] && interface_if=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') [ -z "$interface_if" ] && interface_if=$(ifstatus "${OMR_TRACKER_INTERFACE}_6" 2>/dev/null | jsonfilter -q -e '@["l3_device"]') @@ -501,13 +540,13 @@ set_server_route6() { #multipath_current_config=$(multipath $interface_if | grep "deactivated") interface_current_config=$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state || echo "up") #if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$multipath_current_config" = "" ]; then - if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + if [ "$serverip" != "" ] && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep $serverip | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then [ "$(uci -q get openmptcprouter.settings.debug)" = "true" ] && _log "Set server $server ($serverip) route via $OMR_TRACKER_DEVICE_GATEWAY metric $metric" ip -6 route replace $serverip via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $metric 2>&1 >/dev/null fi } config_list_foreach $server ip server_route - if [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then + if [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ "$(ip -6 route show dev $OMR_TRACKER_DEVICE metric $metric | grep default | grep $OMR_TRACKER_DEVICE_GATEWAY6)" = "" ] && [ "$multipath_config_route" != "off" ] && [ "$interface_current_config" = "up" ] && [ "$interface_up" = "true" ]; then ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $metric 2>&1 >/dev/null fi } @@ -520,14 +559,14 @@ del_server_route() { [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" local metric metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) - [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 - [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 - [ -n "$(ip route show $serverip | grep $OMR_TRACKER_DEVICE)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + [ -n "$metric" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$serverip" ] && [ -n "$(ip route show $serverip | grep $OMR_TRACKER_DEVICE)" ] && ip route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 } config_list_foreach $server ip remove_route - if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then + if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then [ -n "$(ip route show default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE)" ] && ip route del default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 - else + elif [ -n "$OMR_TRACKER_DEVICE" ]; then [ -n "$(ip route show default dev $OMR_TRACKER_DEVICE)" ] && ip route del default dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 fi } @@ -540,13 +579,13 @@ del_server_route6() { [ -n "$serverip" ] && _log "Delete default route via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE" local metric metric=$(uci -q get network.$OMR_TRACKER_INTERFACE.metric) - [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 - [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE metric $metric)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE metric $metric >/dev/null 2>&1 + [ -n "$OMR_TRACKER_DEVICE" ] && [ -n "$metric" ] && [ -n "$(ip -6 route show $serverip dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del $serverip dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 } config_list_foreach $server ip remove_route - if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then + if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then [ -n "$(ip -6 route show default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 - else + elif [ -n "$OMR_TRACKER_DEVICE" ]; then [ -n "$(ip -6 route show default dev $OMR_TRACKER_DEVICE)" ] && ip -6 route del default dev $OMR_TRACKER_DEVICE >/dev/null 2>&1 fi } @@ -604,7 +643,7 @@ interface_up=$(ifstatus "$OMR_TRACKER_INTERFACE" 2>/dev/null | jsonfilter -q -e # An interface in error will never be used in MPTCP if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then - if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ]; then + if [ "$interface_up" = "true" ] && ([ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "modemmanager" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "wireguard" ]); then _log "No answer from $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE), restart interface" _log "Set $OMR_TRACKER_INTERFACE down" ifdown $OMR_TRACKER_INTERFACE @@ -633,7 +672,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then if [ -n "$OMR_TRACKER_DEVICE_IP6" ]; then glorytun-udp path addr $OMR_TRACKER_DEVICE_IP6 dev tun0 set down > /dev/null 2>&1 fi - if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]; then + if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ] && [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ]; then VPN_BASE_INTF="$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.baseintf)" VPN_BASE_INTF_IP=$(ubus call network.interface.$VPN_BASE_INTF status | jsonfilter -e '@["ipv4-address"][0].address' | tr -d "\n") uci -q batch <<-EOF >/dev/null @@ -746,14 +785,7 @@ if [ "$OMR_TRACKER_STATUS" = "ERROR" ] || [ "$interface_up" != "true" ]; then fi if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ]; then - if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then - _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" - ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null - if [ "$(pgrep openmptcprouter-vps)" = "" ]; then - /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 - fi - fi - if [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "hi1" ]; then + if [ "$(uci -q get openmptcprouter.settings.shadowsocksudp)" = "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "hi1" ]; then _log "Tunnel up disable use of ShadowSocks for UDP" uci -q delete shadowsocks-libev.ss_rules.redir_udp if /etc/init.d/shadowsocks-libev rules_exist ; then @@ -761,6 +793,14 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om /etc/init.d/shadowsocks-libev rules_up >/dev/null 2>&1 fi fi + if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then + _log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE" + ip route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE 2>&1 >/dev/null + if [ "$(pgrep openmptcprouter-vps)" = "" ]; then + /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 + fi + [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && conntrack -D -p udp 2>&1 >/dev/null + fi # Set VPN MTU if [ -n "$OMR_TRACKER_LATENCY" ] && ([ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($(date +"%s") - $(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc))) -gt 3600 ]); then @@ -772,12 +812,12 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE="interface" uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.latency="$OMR_TRACKER_LATENCY" if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then - if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then + if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mtu=$mtu - ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 + [ -n "$mtu" ] && ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1 uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") - elif [ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ]; then + elif [ -z "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then if [ -n "$serverip" ] && [ "$serverip" != "127.0.0.1" ]; then local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $serverip) #local mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP 8.8.8.8) @@ -812,6 +852,14 @@ if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "om exit 0 fi +if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]; then + if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" != "up" ]; then + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' + uci -q commit openmptcprouter + fi + exit 0 +fi + if [ "$OMR_TRACKER_PREV_STATUS" != "" ] && [ "$OMR_TRACKER_PREV_STATUS" != "$OMR_TRACKER_STATUS" ]; then _log "$OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) switched up" mail_alert="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.mail_alert)" @@ -839,7 +887,11 @@ fi multipath_config=$(uci -q get "openmtpcprouter.$OMR_TRACKER_INTERFACE.multipath") [ -z "$multipath_config" ] && multipath_config=$(uci -q get "network.$OMR_TRACKER_INTERFACE.multipath" || echo "off") -[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && multipath_config="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" +[ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn)" = "1" ] && { + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "openvpn" ] && multipath_config_route="$(uci -q get openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath || echo "off")" + [ "$(uci -q get openmptcprouter.settings.mptcpovervpn)" = "wireguard" ] && multipath_config_route="$(uci -q get openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath || echo "off")" +} + if [ "$multipath_config" = "master" ]; then #if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && ([ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ] || [ "$(uci -q get openmptcprouter.settings.vpn)" = "mlvpn" ]); then if ([ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]) && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ] && [ "$(uci -q get openmptcprouter.settings.master)" != "balancing" ]; then @@ -928,7 +980,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_route server fi - if [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then ip r replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi fi @@ -940,7 +992,7 @@ if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; th elif [ "$(uci -q get openmptcprouter.settings.master)" != "failover" ]; then config_foreach set_server_route6 server fi - if [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then + if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)" != "" ]; then ip -6 r replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric $(uci -q get network.$OMR_TRACKER_INTERFACE.metric) >/dev/null 2>&1 fi fi @@ -1072,6 +1124,36 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( [ -n "$asn" ] && { uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.asn="$asn" } + + # Routing loop detection + local lanip="$(uci -q get network.lan.ipaddr)" + local masterip + get_master_ip() { + if [ "$(uci -q get openmptcprouter.$1.multipath)" = "master" ]; then + masterip="$(uci -q get openmptcprouter.$1.publicip)" + fi + } + config_load openmptcprouter + config_foreach get_master_ip interface + if [ -n "$lanip" ] && [ -n "$masterip" ] && [ -n "$ipaddr" ] && [ "$ipaddr" = "$masterip" ] && [ "$(uci -q get openmptcprouter.settings.disableloopdetection)" != "1" ]; then + loop=0 + routingloop() { + vpsip="$(uci -q get openmptcprouter.$1.ip)" + if [ -n "$vpsip" ] && [ "$(omr-routing-loop $vpsip $lanip $OMR_TRACKER_DEVICE)" = "detected" ]; then + loop=1 + fi + } + config_load openmptcprouter + config_foreach routingloop server + if [ "$loop" = "1" ]; then + uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.loop='1' + else + uci -q delete openmptcprouter.$OMR_TRACKER_INTERFACE.loop + fi + else + uci -q delete openmptcprouter.$OMR_TRACKER_INTERFACE.loop + fi + local omrtracebox traceboxmtutest() { omr_tracebox_mtu() { @@ -1080,7 +1162,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } - if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then + if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) [ -n "$mtu" ] && { @@ -1108,6 +1190,10 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( } config_load openmptcprouter config_foreach traceboxmtutest server + [ "$(uci -q get openmptcprouter.settings.tracebox)" = "0" ] && { + mptcpsupport="$(omr-mptcp-intf $OMR_TRACKER_DEVICE)" + [ -n "$mptcpsupport" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$mptcpsupport" + } uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up' uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s") } @@ -1140,7 +1226,7 @@ if [ "$(uci -q get openmptcprouter.$OMR_TRACKER_INTERFACE.lc)" = "" ] || [ $(($( omrtracebox="$(omr-tracebox-mptcp $serverip $OMR_TRACKER_DEVICE)" [ -n "$omrtracebox" ] && [ -z "$(echo $omrtracebox | grep error)" ] && uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.mptcp_status="$omrtracebox" } - if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then + if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" != "1" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then if [ -n "$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu)" ]; then mtu=$(uci -q get network.$OMR_TRACKER_INTERFACE.mtu) [ -n "$mtu" ] && { @@ -1309,6 +1395,12 @@ if [ "$(pgrep rpcd)" = "" ] && [ -f /etc/init.d/rpcd ]; then sleep 5 fi +#if [ "$(pgrep ModemManager)" = "" ] && [ -f /etc/init.d/modemmanager ] && [ -n "$(uci -q show network | grep modemmanager)" ] && [ "$(uci -q get openmptcprouter.settings.modemmanager)" != "0" ]; then +# _log "Can't find ModemManager, restart it..." +# /etc/init.d/modemmanager restart +# sleep 5 +#fi + if [ "$(uci -q get v2ray.main.enabled)" = "1" ] && [ -f /etc/init.d/v2ray ] && [ "$(pgrep -f omr-tracker-v2ray)" = "" ] && [ "$(pgrep -f '/etc/init.d/omr-tracker')" = "" ]; then _log "Can't find omr-tracker-v2ray, restart omr-tracker..." /etc/init.d/omr-tracker restart @@ -1354,6 +1446,11 @@ if [ "$(iptables-save | grep omr-bypass)" = "" ] && [ "$(pgrep omr-bypass)" = "" /etc/init.d/omr-bypass fi +if [ -f /etc/backup/installed_packages.txt ]; then + _log "Reinstall packages..." + /etc/init.d/sysupgrade restart +fi + if [ "$(pgrep openmptcprouter-vps)" = "" ] && ([ "$(uci -q show openmptcprouter | grep get_config=\'1\')" != "" ] || [ "$(uci -q show openmptcprouter | grep admin_error=\'1\')" != "" ]); then /etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 sleep 5 diff --git a/omr-6in4/files/etc/init.d/omr-6in4 b/omr-6in4/files/etc/init.d/omr-6in4 index 757ee609c..5bec94c02 100755 --- a/omr-6in4/files/etc/init.d/omr-6in4 +++ b/omr-6in4/files/etc/init.d/omr-6in4 @@ -61,7 +61,8 @@ set_ipv6_state() { set dhcp.lan.ra_default="1" set dhcp.lan.ra_preference="high" set dhcp.lan.ra_management="1" - set dhcp.lan.ra_flags='managed-config' + delete dhcp.lan.ra_flags + add_list dhcp.lan.ra_flags='managed-config' set dhcp.lan.ra_slaac='1' add_list dhcp.lan.ra_flags='other-config' set network.lan.ipv6="1" diff --git a/omr-tracker/files/bin/omr-tracker b/omr-tracker/files/bin/omr-tracker index bd8bf7d3d..f78571aab 100755 --- a/omr-tracker/files/bin/omr-tracker +++ b/omr-tracker/files/bin/omr-tracker @@ -238,7 +238,7 @@ while true; do OMR_TRACKER_DEVICE_GATEWAY6= serverip_ping=false - if [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then + if [ -n "$OMR_TRACKER_DEVICE" ] && [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then if [ -n "$(ip link show $OMR_TRACKER_DEVICE | grep UP)" ]; then # retrieve iface ip and gateway if [ "$OMR_TRACKER_INTERFACE_PROTO" != "dhcpv6" ]; then diff --git a/omr-tracker/files/etc/config/omr-tracker b/omr-tracker/files/etc/config/omr-tracker index c743b7656..3ca2b5ac9 100755 --- a/omr-tracker/files/etc/config/omr-tracker +++ b/omr-tracker/files/etc/config/omr-tracker @@ -20,7 +20,7 @@ config defaults 'defaults' list hosts6 '2620:fe::9' list hosts6 '2001:4860:4860::8888' list hosts6 '2001:4860:4860::8844' - option timeout '2' + option timeout '10' option tries '3' option interval '2' option interval_tries '1' diff --git a/openmptcprouter-full/Makefile b/openmptcprouter-full/Makefile index eab020f97..31282b251 100755 --- a/openmptcprouter-full/Makefile +++ b/openmptcprouter-full/Makefile @@ -30,7 +30,7 @@ MY_DEPENDS := \ bind-dig \ libnetfilter-conntrack ebtables ebtables-utils ip-full \ iptables-mod-iface iptables-mod-ipmark iptables-mod-hashlimit iptables-mod-condition iptables-mod-trace iptables-mod-conntrack-extra iptables-mod-account \ - kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra \ + kmod-nf-nat kmod-nf-nathelper kmod-nf-nathelper-extra iptables-mod-extra conntrack \ iptables-mod-ipsec kmod-crypto-authenc kmod-ipsec kmod-ipsec4 kmod-ipsec6 kmod-ipt-ipsec \ wireless-tools \ libiwinfo-lua \ @@ -77,12 +77,12 @@ MY_DEPENDS := \ !TARGET_mvebu:kmod-usb-serial !TARGET_mvebu:kmod-usb-serial-option !TARGET_mvebu:kmod-usb-serial-wwan !TARGET_mvebu:usb-modeswitch !TARGET_mvebu:uqmi \ !TARGET_mvebu:umbim !TARGET_mvebu:kmod-mii !TARGET_mvebu:kmod-usb-net !TARGET_mvebu:kmod-usb-wdm !TARGET_mvebu:kmod-usb-net-qmi-wwan !TARGET_mvebu:kmod-usb-net-cdc-mbim !TARGET_mvebu:umbim \ !TARGET_mvebu:kmod-usb-net-huawei-cdc-ncm !TARGET_mvebu:kmod-usb-net-rndis !TARGET_mvebu:kmod-usb-net-cdc-ether !TARGET_mvebu:kmod-usb-net-ipheth !TARGET_mvebu:usbmuxd \ - kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su \ - !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 \ + kmod-rt2800-usb kmod-rtl8xxxu kmod-rtl8192cu kmod-net-rtl8192su kmod-rtl8812au-ct \ + !TARGET_mvebu:luci-proto-qmi wpad-basic kmod-mt7601u kmod-rtl8187 TARGET_r4s:kmod-r8168 (TARGET_x86||TARGET_x86_64):kmod-usb-net-rtl8152 \ luci-app-mlvpn mlvpn 464xlat !TARGET_mvebu:kmod-usb-net-smsc75xx kmod-zram kmod-swconfig swconfig kmod-ipt-nat kmod-ipt-nat6 luci-app-https-dns-proxy kmod-tcp-nanqinlang (TARGET_x86_64||aarch64):kmod-tcp-bbr2 iptables-mod-ipopt igmpproxy ss iptraf-ng \ luci-app-acl block-mount blockd fstools luci-app-shutdown libwebp luci-proto-gre tcptraceroute luci-proto-mbim kmod-rtl8xxxu kmod-ath9k-htc luci-app-ttyd luci-mod-dashboard (TARGET_x86||TARGET_x86_64):rtl8192eu-firmware kmod-usb2 libustream-wolfssl (TARGET_x86||TARGET_x86_64):kmod-ixgbevf \ hwinfo (TARGET_x86||TARGET_x86_64):dmidecode luci-app-packet-capture kmod-bonding luci-proto-bonding luci-app-sysupgrade \ - luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard (TARGET_x86||TARGET_x86_64):kmod-r8125 + luci-theme-openwrt-2020 luci-proto-wireguard luci-app-wireguard (TARGET_x86||TARGET_x86_64):kmod-r8125 TARGET_x86_64:kmod-atlantic # luci-theme-bootstrap luci-theme-openwrt-2020 luci-theme-openwrt luci-app-status # luci-proto-bonding luci-app-statistics luci-proto-gre # softethervpn5-client softethervpn5-server luci-app-nginx-ha diff --git a/openmptcprouter/files/bin/blocklanfw b/openmptcprouter/files/bin/blocklanfw new file mode 100755 index 000000000..0f4a85367 --- /dev/null +++ b/openmptcprouter/files/bin/blocklanfw @@ -0,0 +1,76 @@ +#!/bin/sh +ss_rules_fw_drop() { + fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done + fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "iptables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done +} + +ss_rules6_fw_drop() { + fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done + fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "ip6tables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done +} + +v2r_rules_fw_drop() { + fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done + fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "iptables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done +} + +v2ray_rules6_fw_drop() { + fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done + fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "ip6tables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done +} + +if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then + ss_rules6_fw_drop + ss_rules_fw_drop +elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ]; then + v2r_rules_fw_drop + v2ray_rules6_fw_drop +fi diff --git a/openmptcprouter/files/bin/omr-test-speed-server b/openmptcprouter/files/bin/omr-test-speed-server new file mode 100755 index 000000000..df61352ec --- /dev/null +++ b/openmptcprouter/files/bin/omr-test-speed-server @@ -0,0 +1,26 @@ +#!/bin/sh +SERVER=$1 +INTERFACE=$2 +[ -z "$SERVER" ] && SERVER="vps" +KEY=$(uci -q get openmptcprouter.$SERVER.token) +HOST=$(uci -q get openmptcprouter.$SERVER.ip | awk '{print $1}') +PORT=$(uci -q get openmptcprouter.$SERVER.port) +MP=false +if [ -n "$KEY" ] && [ -n "$HOST" ] && [ -n "$PORT" ]; then + trap : HUP INT TERM + echo "Download test via server ${SERVER}:" + if [ -n "$INTERFACE" ]; then + if [ "$(multipath ${INTERFACE} | grep default)" ]; then + MP=true + /etc/init.d/omr-tracker stop 2>&1 >/dev/null + multipath ${INTERFACE} off + fi + curl -k -o /dev/null --interface $INTERFACE -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + if [ $MP ]; then + multipath ${INTERFACE} on + /etc/init.d/omr-tracker start & 2>&1 >/dev/null + fi + else + curl -k -o /dev/null -H "Authorization: Bearer ${KEY}" https://${HOST}:${PORT}/speedtest || echo + fi +fi \ No newline at end of file diff --git a/openmptcprouter/files/etc/hotplug.d/iface/00-nego b/openmptcprouter/files/etc/hotplug.d/iface/00-nego new file mode 100644 index 000000000..67e62dcec --- /dev/null +++ b/openmptcprouter/files/etc/hotplug.d/iface/00-nego @@ -0,0 +1,3 @@ +#!/bin/sh +# Needed for some device, like rtl8156 2.5G USB adapter +[ "$ACTION" = "ifup" ] && [ -n "$DEVICE" ] && [ -n "$(lsusb | grep 8156)" ] [ -n "$(ethtool $DEVICE | grep 2500)" ] && ethtool -s $DEVICE autoneg on \ No newline at end of file diff --git a/openmptcprouter/files/etc/init.d/mptcpovervpn b/openmptcprouter/files/etc/init.d/mptcpovervpn index 9ada8c50e..b36425041 100755 --- a/openmptcprouter/files/etc/init.d/mptcpovervpn +++ b/openmptcprouter/files/etc/init.d/mptcpovervpn @@ -1,13 +1,21 @@ #!/bin/sh /etc/rc.common -# Copyright (C) 2019 Ycarus (Yannick Chabanois) +# Copyright (C) 2019 - 2021 Ycarus (Yannick Chabanois) for OpenMPTCProuter # Released under GPL 3. See LICENSE for the full terms. { - START=70 + START=99 STOP=10 USE_PROCD=1 } +wireguard_restart() { + local interface=$1 + if [ "$(uci -q get network.${interface}.proto)" = "wireguard" ] && [ -n "$(uci -q get network.${interface}.fwmark)" ]; then + ifdown ${interface} + ifup ${interface} + fi +} + _getremoteip() { [ "$(uci -q get openmptcprouter.$1.master)" = "1" ] && { remoteip=$(uci -q get openmptcprouter.$1.ip | awk '{print $1}') @@ -17,7 +25,7 @@ _getremoteip() { mptcp_over_vpn() { local interface=$1 - nbintf=$(($nbintf+1)) + [ -n "$(uci show firewall.zone_wan.network | grep $interface)" ] && nbintf=$(($nbintf+1)) if [ "$(uci -q get openmptcprouter.${interface}.multipathvpn)" = "1" ]; then if [ "$(uci -q get network.${interface})" = "" ]; then uci -q batch <<-EOF >/dev/null @@ -210,15 +218,36 @@ start_service() [ -z "$vpn" ] && vpn="openvpn" config_load openmptcprouter config_foreach mptcp_over_vpn interface - if [ "$nbintf" = "$nbintfvpn" ] && [ "$nbintf" != "0" ]; then + if [ "$nbintf" = "$nbintfvpn" ] && [ "$nbintf" != "0" ] && [ "$nbintfvpn" != "0" ]; then uci -q batch <<-EOF >/dev/null - set shadowsocks-libev.sss0.disabled='1' - set glorytun.vpn.host='10.255.250.1' - set glorytun-udp.vpn.host='10.255.250.1' - commit glorytun - commit glorytun-udp + set openmptcprouter.settings.allmptcpovervpn='1' + commit openmptcprouter EOF - elif [ "$(uci -q get glorytun.vpn.host)" = "10.255.250.1" ] && [ "$nbintf" != "$nbintfvpn" ]; then + else + uci -q batch <<-EOF >/dev/null + set openmptcprouter.settings.allmptcpovervpn='0' + commit openmptcprouter + EOF + fi + if [ "$nbintf" = "$nbintfvpn" ] && [ "$nbintf" != "0" ]; then + if [ "$vpn" = "openvpn" ]; then + uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.sss0.disabled='1' + set glorytun.vpn.host='10.255.250.1' + set glorytun-udp.vpn.host='10.255.250.1' + commit glorytun + commit glorytun-udp + EOF + else + uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.sss0.disabled='1' + set glorytun.vpn.host='10.255.247.1' + set glorytun-udp.vpn.host='10.255.247.1' + commit glorytun + commit glorytun-udp + EOF + fi + elif ([ "$(uci -q get glorytun.vpn.host)" = "10.255.250.1" ] || [ "$(uci -q get glorytun.vpn.host)" = "10.255.247.1" ]) && [ "$nbintf" != "$nbintfvpn" ]; then uci -q batch <<-EOF >/dev/null delete shadowsocks-libev.sss0.disabled set glorytun.vpn.host="$(uci -q get openmptcprouter.vps.ip | awk '{print $1}')" @@ -229,14 +258,25 @@ start_service() fi NBCPU=$(grep -c '^processor' /proc/cpuinfo | tr -d "\n") if [ "$nbintfvpn" != 0 ]; then - uci -q batch <<-EOF >/dev/null - set shadowsocks-libev.mptcpovervpn=server - set shadowsocks-libev.mptcpovervpn.server_port="$(uci -q get shadowsocks-libev.sss0.server_port)" - set shadowsocks-libev.mptcpovervpn.key="$(uci -q get shadowsocks-libev.sss0.key)" - set shadowsocks-libev.mptcpovervpn.method="$(uci -q get shadowsocks-libev.sss0.method)" - set shadowsocks-libev.mptcpovervpn.server="10.255.250.1" - delete shadowsocks-libev.mptcpovervpn.disabled - EOF + if [ "$vpn" = "openvpn" ]; then + uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.mptcpovervpn=server + set shadowsocks-libev.mptcpovervpn.server_port="$(uci -q get shadowsocks-libev.sss0.server_port)" + set shadowsocks-libev.mptcpovervpn.key="$(uci -q get shadowsocks-libev.sss0.key)" + set shadowsocks-libev.mptcpovervpn.method="$(uci -q get shadowsocks-libev.sss0.method)" + set shadowsocks-libev.mptcpovervpn.server="10.255.250.1" + delete shadowsocks-libev.mptcpovervpn.disabled + EOF + else + uci -q batch <<-EOF >/dev/null + set shadowsocks-libev.mptcpovervpn=server + set shadowsocks-libev.mptcpovervpn.server_port="$(uci -q get shadowsocks-libev.sss0.server_port)" + set shadowsocks-libev.mptcpovervpn.key="$(uci -q get shadowsocks-libev.sss0.key)" + set shadowsocks-libev.mptcpovervpn.method="$(uci -q get shadowsocks-libev.sss0.method)" + set shadowsocks-libev.mptcpovervpn.server="10.255.247.1" + delete shadowsocks-libev.mptcpovervpn.disabled + EOF + fi for c in $(seq 1 $NBCPU); do uci -q batch <<-EOF >/dev/null set shadowsocks-libev.hivpn$c=ss_redir @@ -257,6 +297,8 @@ start_service() uci -q batch <<-EOF >/dev/null commit shadowsocks-libev EOF + /etc/init.d/shadowsocks restart + /etc/init.d/openvpn restart elif [ "$(uci -q get shadowsocks-libev.hivpn1)" != "" ]; then for c in $(seq 1 $NBCPU); do uci -q batch <<-EOF >/dev/null @@ -271,6 +313,16 @@ start_service() commit shadowsocks-libev EOF fi + if [ "$BOOT" = "1" ]; then + config_load network + config_foreach wireguard_restart interface + fi + +} + +boot() { + BOOT=1 + start } service_triggers() { diff --git a/openmptcprouter/files/etc/init.d/openmptcprouter-vps b/openmptcprouter/files/etc/init.d/openmptcprouter-vps index b2ea9340b..7e2f4c4e1 100755 --- a/openmptcprouter/files/etc/init.d/openmptcprouter-vps +++ b/openmptcprouter/files/etc/init.d/openmptcprouter-vps @@ -173,7 +173,7 @@ _set_wireguard_vps() { local interface=$1 proto=$(uci -q get network.${interface}.proto) if [ "$proto" = "wireguard" ]; then - ip="$(uci -q get network.${interface}.addresses)" + ip="$(uci -q get network.${interface}.addresses | cut -d/ -f1)" key="$(uci -q get network.${interface}.public_key)" if [ -z "$ipskey" ]; then ipskey='{"ip": "'$ip'", "key": "'$key'"}' @@ -185,8 +185,12 @@ _set_wireguard_vps() { config_load network config_foreach _get_wg_ipskey interface local settings - settings='{"peers": ['$ipskey']}' - echo $(_set_json "wireguard" "$settings") + if [ -n "$ipskey" ]; then + settings='{"peers": ['$ipskey']}' + echo $(_set_json "wireguard" "$settings") + else + echo 1 + fi } get_openvpn_key() { @@ -560,7 +564,6 @@ _get_gre_tunnel() { set shadowsocks-libev.oip${i}server=server set shadowsocks-libev.oip${i}server.label="Server with public IP $publicaddr" set shadowsocks-libev.oip${i}server.server_port="$ssport" - set shadowsocks-libev.oip${i}server.disabled="1" set shadowsocks-libev.oip${i}server.server="$(uci -q get shadowsocks-libev.sss0.server)" set shadowsocks-libev.oip${i}server.method="$(uci -q get shadowsocks-libev.sss0.method)" set shadowsocks-libev.oip${i}server.key="$(uci -q get shadowsocks-libev.sss0.key)" @@ -585,6 +588,9 @@ _get_gre_tunnel() { set shadowsocks-libev.oip${i}_rule.local_default='bypass' set shadowsocks-libev.oip${i}_rule.redir_tcp="oip${i}" EOF + if [ "$(uci -q get shadowsocks-libev.oip${i}server.disabled)" = "" ]; then + uci -q set shadowsocks-libev.oip${i}server.disabled="1" + fi fi i=$((i+1)) done @@ -822,8 +828,8 @@ _set_vpn_ip() { vpnip_local=$(ip -4 -br addr ls dev ${vpnifname} | awk -F'[ /]+' '{print $3}') vpnip_remote_current="$(echo "$vps_config" | jsonfilter -q -e '@.vpn.localip')" vpnip_remote=$(ip -4 r list dev ${vpnifname} | grep via | grep -v default | grep -v / | grep -v metric | awk '{print $1}' | tr -d "\n") - [ -z "$vpnip_remote" ] && vpnip_remote=$(ip -4 r list dev ${vpnifname} | grep kernel | awk '{print $1}' | tr -d "\n") - [ -z "$vpnip_remote" ] && vpnip_remote=$(ip -4 r list dev ${vpnifname} | grep "proto static src" | awk '{print $3}' | tr -d "\n") + [ -z "$vpnip_remote" ] && [ -n "$vpnifname" ] && vpnip_remote=$(ip -4 r list dev ${vpnifname} | grep kernel | awk '{print $1}' | tr -d "\n") + [ -z "$vpnip_remote" ] && [ -n "$vpnifname" ] && vpnip_remote=$(ip -4 r list dev ${vpnifname} | grep "proto static src" | awk '{print $3}' | tr -d "\n") [ -z "$vpnip_remote" ] && vpnip_remote=$(ifstatus omrvpn | jsonfilter -e '@.route[0].nexthop') ula="$(uci -q get network.globals.ula_prefix)" ula_current="$(echo "$vps_config" | jsonfilter -q -e '@.ip6in4.ula')" @@ -1100,13 +1106,21 @@ _set_vps_firewall() { vpsfwlist=$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d') settings='{"name" : "open router"}' fw_list=$(_set_json "shorewalllist" "$settings") - vpsfwlist="$vpsfwlist\n$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" + if [ -n "$vpsfwlist" ]; then + vpsfwlist="$vpsfwlist\n$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" + else + vpsfwlist="$(echo $fw_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" + fi settings='{"name" : "redirect router","ipproto" : "ipv6"}' fw6_list=$(_set_json "shorewalllist" "$settings") vpsfw6list=$(echo $fw6_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d') settings='{"name" : "open router","ipproto" : "ipv6"}' fw6_list=$(_set_json "shorewalllist" "$settings") - vpsfw6list="$vpsfw6list\n$(echo $fw6_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" + if [ -n "$vpsfw6list" ]; then + vpsfw6list="$vpsfw6list\n$(echo $fw6_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" + else + vpsfw6list="$(echo $fw6_list | jsonfilter -q -e '@.list[*]' | sed '/^[[:space:]]*$/d')" + fi config_load firewall config_foreach _vps_firewall_redirect_port redirect config_foreach _vps_firewall_redirect_port rule @@ -1800,7 +1814,7 @@ _config_service() { [ -z "$(_set_openvpn_vps)" ] && error=1 [ -z "$(_set_mlvpn_vps)" ] && error=1 _set_vps_firewall - _set_wireguard_vps + [ -z "$(_set_wireguard_vps)" ] && error=1 fi _backup_list redirect_port="0" diff --git a/openmptcprouter/files/etc/uci-defaults/000-omr-update b/openmptcprouter/files/etc/uci-defaults/000-omr-update index 6e16cc6b0..e86103c55 100755 --- a/openmptcprouter/files/etc/uci-defaults/000-omr-update +++ b/openmptcprouter/files/etc/uci-defaults/000-omr-update @@ -4,15 +4,8 @@ cd /etc/uci-defaults || exit 0 source /etc/os-release OMRVERSION=$(echo $VERSION | sed 's/v//') -files="$(ls /etc/uci-defaults/)" -[ -n "$files" ] && { - mkdir -p /usr/share/omr-update - if [ "$(grep rom /etc/mtab)" = "" ]; then - rm /usr/share/omr-update/* - cp /etc/uci-defaults/* /usr/share/omr-update - fi - uci -q set openmptcprouter.settings=settings - uci -q set openmptcprouter.settings.version=${OMRVERSION} - uci -q commit -} +uci -q set openmptcprouter.settings=settings +uci -q set openmptcprouter.settings.version=${OMRVERSION} +uci -q commit + exit 0 diff --git a/openmptcprouter/files/etc/uci-defaults/0000-omr-update b/openmptcprouter/files/etc/uci-defaults/0000-omr-update new file mode 100755 index 000000000..82a2cee3b --- /dev/null +++ b/openmptcprouter/files/etc/uci-defaults/0000-omr-update @@ -0,0 +1,14 @@ +#!/bin/sh + +cd /etc/uci-defaults || exit 0 +source /etc/os-release + +files="$(ls /etc/uci-defaults/)" +[ -n "$files" ] && { + mkdir -p /usr/share/omr-update + if [ "$(grep rom /etc/mtab)" = "" ]; then + rm /usr/share/omr-update/* + cp /etc/uci-defaults/* /usr/share/omr-update + fi +} +exit 0 diff --git a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns index af5a4877c..6db34b39d 100755 --- a/openmptcprouter/files/etc/uci-defaults/1940-omr-dns +++ b/openmptcprouter/files/etc/uci-defaults/1940-omr-dns @@ -200,6 +200,10 @@ if [ -z "$(uci -q get unbound.fwd_adguard_family)" ]; then EOF fi +if [ -z "$(grep nameserver /etc/resolv.conf)" ]; then + echo "nameserver 127.0.0.1" > /etc/resolv.conf +fi + rm -f /tmp/luci-indexcache exit 0 diff --git a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn index bb4dbf559..d1f5d8b86 100755 --- a/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn +++ b/openmptcprouter/files/etc/uci-defaults/2020-omr-vpn @@ -137,7 +137,7 @@ if [ "$(uci -q get glorytun-udp.vpn.key)" = "" ] && [ "$(uci -q get glorytun.vpn set glorytun-udp.vpn.key=$(uci -q get glorytun.vpn.key) set glorytun-udp.vpn.host=$(uci -q get glorytun.vpn.host) EOF - if [ "$(uci -q get glorytun-udp.vpn.proto)" = "udp" ]; then + if [ "$(uci -q get glorytun.vpn.proto)" = "udp" ]; then uci -q batch <<-EOF >/dev/null set glorytun-udp.vpn.enable=1 set glorytun.vpn.enable=0 diff --git a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm index f148a9916..d8c232752 100755 --- a/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm +++ b/openmptcprouter/files/etc/uci-defaults/2040-omr-sqm @@ -74,24 +74,24 @@ if [ "$(uci -q get openmptcprouter.settings.version)" = "" ]; then fi fi -#if [ "$(uci -q get sqm.omrvpn)" = "" ]; then -# uci -q batch <<-EOF >/dev/null -# set sqm.omrvpn=queue -# set sqm.omrvpn.qdisc="fq_codel" -# set sqm.omrvpn.script="simple.qos" -# set sqm.omrvpn.qdisc_advanced='0' -# set sqm.omrvpn.linklayer='none' -# set sqm.omrvpn.enabled='1' -# set sqm.omrvpn.interface=tun0 -# set sqm.omrvpn.download='0' -# set sqm.omrvpn.upload='0' -# set sqm.omrvpn.debug_logging='0' -# set sqm.omrvpn.verbosity='5' -# set sqm.omrvpn.iqdisc_opts='autorate-ingress dual-dsthost' -# set sqm.omrvpn.eqdisc_opts='dual-srchost' -# commit sqm -# EOF -#fi +if [ "$(uci -q get sqm.omrvpn)" = "" ]; then + uci -q batch <<-EOF >/dev/null + set sqm.omrvpn=queue + set sqm.omrvpn.qdisc="cake" + set sqm.omrvpn.script="piece_of_cake.qos" + set sqm.omrvpn.qdisc_advanced='0' + set sqm.omrvpn.linklayer='none' + set sqm.omrvpn.enabled='1' + set sqm.omrvpn.interface=tun0 + set sqm.omrvpn.download='0' + set sqm.omrvpn.upload='0' + set sqm.omrvpn.debug_logging='0' + set sqm.omrvpn.verbosity='5' + set sqm.omrvpn.overhead='40' + set sqm.omrvpn.iqdisc_opts='autorate-ingress' + commit sqm + EOF +fi rm -f /tmp/luci-indexcache diff --git a/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan b/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan index 42d8f2555..b321023e0 100755 --- a/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan +++ b/openmptcprouter/files/etc/uci-defaults/2090-omr-wwan @@ -7,6 +7,8 @@ if [ "$(grep usbmode /etc/rc.local)" = "" ]; then /sbin/usbmode -l /bin/sleep 3 /sbin/usbmode -s + /bin/sleep 3 + /etc/init.d/getserveratboot restart exit 0 EOF fi diff --git a/openmptcprouter/files/etc/uci-defaults/2093-opkg b/openmptcprouter/files/etc/uci-defaults/2093-opkg new file mode 100755 index 000000000..4cad586db --- /dev/null +++ b/openmptcprouter/files/etc/uci-defaults/2093-opkg @@ -0,0 +1,19 @@ +#!/bin/sh +source /etc/os-release +if [ "$ID" = "openmptcprouter" ]; then + cat > "/etc/opkg/customfeeds.conf" <<-EOF + src/gz openwrt_luci https://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/luci + src/gz openwrt_packages https://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/packages + src/gz openwrt_base https://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/base + src/gz openwrt_routing https://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/routing + src/gz openwrt_telephony https://packages.openmptcprouter.com/${VERSION_ID}/${OPENWRT_ARCH}/telephony + EOF + TARGET="$(cat /etc/banner | awk '/TARGET/ {print $2}')" + cat > "/etc/opkg/distfeeds.conf" <<-EOF + src/gz openmptcprouter_core https://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/targets/${OPENWRT_BOARD}/packages + src/gz openmptcprouter_base https://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/packages/${OPENWRT_ARCH}/base + src/gz openmptcprouter_luci https://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/packages/${OPENWRT_ARCH}/luci + src/gz openmptcprouter_openmptcprouter https://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/packages/${OPENWRT_ARCH}/openmptcprouter + src/gz openmptcprouter_packages https://download.openmptcprouter.com/release/${VERSION_ID}/${TARGET}/packages/${OPENWRT_ARCH}/packages + EOF +fi \ No newline at end of file diff --git a/shadowsocks-libev/files/shadowsocks-libev.config b/shadowsocks-libev/files/shadowsocks-libev.config index 2bf7def6b..c9ba382fb 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.config +++ b/shadowsocks-libev/files/shadowsocks-libev.config @@ -28,7 +28,7 @@ config ss_redir hi2 config ss_rules 'ss_rules' option disabled 0 - option redir_tcp 'hi' + option redir_tcp 'hi1' option src_default 'forward' option dst_default 'forward' option local_default 'forward' diff --git a/shadowsocks-libev/files/shadowsocks-libev.init b/shadowsocks-libev/files/shadowsocks-libev.init index 04810e123..f9a98d89c 100755 --- a/shadowsocks-libev/files/shadowsocks-libev.init +++ b/shadowsocks-libev/files/shadowsocks-libev.init @@ -196,11 +196,15 @@ ss_rules() { all_ss_redir_ports=$min_ss_redir_ports fi local_port_tcp="$all_ss_redir_ports" - #local_port_udp="$all_ss_redir_ports" - eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" + if [ "$ss_rules_redir_udp_$redir_udp" = "all" ] || [ "$ss_rules_redir_udp_$redir_udp" = "hi1" ]; then + local_port_udp="$min_ss_redir_ports" + fi + #eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" local_port_tcp6="$all_ss_redir_ports" - #local_port_udp6="$all_ss_redir_ports" - eval local_port_udp6="\$ss_rules6_redir_udp_$redir_udp" + if [ "$ss_rules_redir_udp_$redir_udp" = "all" ] || [ "$ss_rules_redir_udp_$redir_udp" = "hi1" ]; then + local_port_udp6="$min_ss_redir_ports" + fi + #eval local_port_udp6="\$ss_rules6_redir_udp_$redir_udp" else eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp" eval local_port_udp="\$ss_rules_redir_udp_$redir_udp" @@ -308,7 +312,10 @@ server_state() { } rules_up() { - rules_exist && return 0 + rules_exist && { + [ -f /bin/blocklanfw ] && /bin/blocklanfw 2>&1 >/dev/null + return 0 + } [ "$(uci -q get shadowsocks-libev.ss_rules.disabled)" = "1" ] && return 0 enabled="0" passkey="" @@ -325,6 +332,7 @@ rules_up() { logger -t "Shadowsocks" "Reload omr-bypass rules" /etc/init.d/omr-bypass reload_rules } + [ -f /bin/blocklanfw ] && /bin/blocklanfw 2>&1 >/dev/null } rules_down() { diff --git a/shadowsocks-libev/files/shadowsocks.conf b/shadowsocks-libev/files/shadowsocks.conf index 159ea3860..9c6f64727 100755 --- a/shadowsocks-libev/files/shadowsocks.conf +++ b/shadowsocks-libev/files/shadowsocks.conf @@ -23,6 +23,8 @@ net.ipv4.tcp_tw_reuse = 1 #net.ipv4.tcp_tw_recycle = 0 # short FIN timeout #net.ipv4.tcp_fin_timeout = 60 +# increase max orphans +net.ipv4.tcp_max_orphans = 16384 # short keepalive time #net.ipv4.tcp_keepalive_time = 2400 # outbound port range diff --git a/shadowsocks-libev/files/ss-rules b/shadowsocks-libev/files/ss-rules index 4ae5fb5b1..380a5493a 100755 --- a/shadowsocks-libev/files/ss-rules +++ b/shadowsocks-libev/files/ss-rules @@ -275,7 +275,7 @@ ss_rules_iptchains_mkprerules() { local proto="$1" if [ -z "$o_ifnames" ]; then - echo "-I PREROUTING 1 -p $proto -j ssr_${rule}_pre_src" + echo "-A PREROUTING -p $proto -j ssr_${rule}_pre_src" else echo $o_ifnames \ | tr ' ' '\n' \ diff --git a/shadowsocks-libev/files/ss-rules6 b/shadowsocks-libev/files/ss-rules6 index 7960e2f90..8d6b28db1 100755 --- a/shadowsocks-libev/files/ss-rules6 +++ b/shadowsocks-libev/files/ss-rules6 @@ -149,11 +149,13 @@ ss_rules6_iptchains_init() { } ss_rules6_iptchains_init_mark() { - ip6tables-restore -w --noflush <<-EOF - *mangle - -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 - COMMIT - EOF + if [ "$(ip6tables -w -t mangle -L PREROUTING | grep ss_rules6_dst_bypass_all)" = "" ]; then + ip6tables-restore -w --noflush <<-EOF + *mangle + -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x6539 + COMMIT + EOF + fi } @@ -257,7 +259,7 @@ ss_rules6_iptchains_mkprerules() { local proto="$1" if [ -z "$o_ifnames" ]; then - echo "-I PREROUTING 1 -p $proto -j ssr6_${rule}_pre_src" + echo "-A PREROUTING -p $proto -j ssr6_${rule}_pre_src" else echo $o_ifnames \ | tr ' ' '\n' \ diff --git a/shortcut-fe/Makefile b/shortcut-fe/Makefile new file mode 100644 index 000000000..54711c46a --- /dev/null +++ b/shortcut-fe/Makefile @@ -0,0 +1,77 @@ +# +# Copyright (c) 2014 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=shortcut-fe +PKG_RELEASE:=2 +PKG_CONFIG_DEPENDS := CONFIG_IPV6 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/shortcut-fe + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:= + TITLE:=Kernel driver for SFE + FILES:=$(PKG_BUILD_DIR)/shortcut-fe.ko $(if $(CONFIG_IPV6),$(PKG_BUILD_DIR)/shortcut-fe-ipv6.ko,) + KCONFIG:=CONFIG_NF_CONNTRACK_EVENTS=y \ + CONFIG_NF_CONNTRACK_TIMEOUT=y \ + CONFIG_SHORTCUT_FE=y \ + CONFIG_XFRM=y + AUTOLOAD:=$(call AutoLoad,09,shortcut-fe shortcut-fe-ipv6) +endef + +define KernelPackage/shortcut-fe/Description +Shortcut is an in-Linux-kernel IP packet forwarding engine. +endef + +define KernelPackage/shortcut-fe/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) ./files/usr/bin/sfe_dump $(1)/usr/bin +endef + +define KernelPackage/shortcut-fe-cm + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe + TITLE:=Kernel driver for SFE + FILES:=$(PKG_BUILD_DIR)/shortcut-fe-cm.ko + KCONFIG:=CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y +endef + +define KernelPackage/shortcut-fe-cm/Description +Simple connection manager for the Shortcut forwarding engine. +endef + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + modules \ + $(if $(CONFIG_IPV6),EXTRA_CFLAGS="-DSFE_SUPPORT_IPV6" SFE_SUPPORT_IPV6=y,) +endef + +#ifneq ($(CONFIG_PACKAGE_kmod-shortcut-fe)$(CONFIG_PACKAGE_kmod-shortcut-fe-cm),) +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/shortcut-fe + $(CP) -rf $(PKG_BUILD_DIR)/sfe.h $(1)/usr/include/shortcut-fe +endef +#endif + +$(eval $(call KernelPackage,shortcut-fe)) +$(eval $(call KernelPackage,shortcut-fe-cm)) diff --git a/shortcut-fe/files/usr/bin/sfe_dump b/shortcut-fe/files/usr/bin/sfe_dump new file mode 100644 index 000000000..2a224e0ca --- /dev/null +++ b/shortcut-fe/files/usr/bin/sfe_dump @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# Permission to use, copy, modify, and/or distribute this software for +# any purpose with or without fee is hereby granted, provided that the +# above copyright notice and this permission notice appear in all copies. +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +#@sfe_dump +#@example : sfe_dump (ipv4|ipv6) +sfe_dump(){ + [ -e "/dev/sfe_ipv4" ] || { + dev_num=$(cat /sys/sfe_ipv4/debug_dev) + mknod /dev/sfe_ipv4 c $dev_num 0 + } + [ -e "/dev/sfe_ipv6" ] || { + dev_num=$(cat /sys/sfe_ipv6/debug_dev) + mknod /dev/sfe_ipv6 c $dev_num 0 + } + cat /dev/sfe_$1 +} + +if [ -z "$1" ]; then + sfe_dump ipv4 + sfe_dump ipv6 +else + sfe_dump $1 +fi diff --git a/shortcut-fe/src/Kconfig b/shortcut-fe/src/Kconfig new file mode 100644 index 000000000..487f1e065 --- /dev/null +++ b/shortcut-fe/src/Kconfig @@ -0,0 +1,14 @@ +# +# Shortcut forwarding engine +# + +config SHORTCUT_FE + tristate "Shortcut Forwarding Engine" + depends on NF_CONNTRACK + ---help--- + Shortcut is a fast in-kernel packet forwarding engine. + + To compile this code as a module, choose M here: the module will be + called shortcut-fe. + + If unsure, say N. diff --git a/shortcut-fe/src/Makefile b/shortcut-fe/src/Makefile new file mode 100644 index 000000000..3b1ceaa44 --- /dev/null +++ b/shortcut-fe/src/Makefile @@ -0,0 +1,23 @@ +# +# Makefile for Shortcut FE. +# + +obj-m += shortcut-fe.o + +ifdef SFE_SUPPORT_IPV6 +obj-m += shortcut-fe-ipv6.o +endif + +obj-m += shortcut-fe-cm.o + +shortcut-fe-objs := \ + sfe_ipv4.o + +ifdef SFE_SUPPORT_IPV6 +shortcut-fe-ipv6-objs := \ + sfe_ipv6.o +endif + +shortcut-fe-cm-objs := \ + sfe_cm.o + diff --git a/shortcut-fe/src/sfe.h b/shortcut-fe/src/sfe.h new file mode 100644 index 000000000..279e7b3dc --- /dev/null +++ b/shortcut-fe/src/sfe.h @@ -0,0 +1,114 @@ +/* + * sfe.h + * Shortcut forwarding engine. + * + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * The following are debug macros used throughout the SFE. + * + * The DEBUG_LEVEL enables the followings based on its value, + * when dynamic debug option is disabled. + * + * 0 = OFF + * 1 = ASSERTS / ERRORS + * 2 = 1 + WARN + * 3 = 2 + INFO + * 4 = 3 + TRACE + */ +#define DEBUG_LEVEL 2 + +#if (DEBUG_LEVEL < 1) +#define DEBUG_ASSERT(s, ...) +#define DEBUG_ERROR(s, ...) +#else +#define DEBUG_ASSERT(c, s, ...) if (!(c)) { pr_emerg("ASSERT: %s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); BUG(); } +#define DEBUG_ERROR(s, ...) pr_err("%s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if defined(CONFIG_DYNAMIC_DEBUG) +/* + * Compile messages for dynamic enable/disable + */ +#define DEBUG_WARN(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DEBUG_INFO(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define DEBUG_TRACE(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else + +/* + * Statically compile messages at different levels + */ +#if (DEBUG_LEVEL < 2) +#define DEBUG_WARN(s, ...) +#else +#define DEBUG_WARN(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if (DEBUG_LEVEL < 3) +#define DEBUG_INFO(s, ...) +#else +#define DEBUG_INFO(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#if (DEBUG_LEVEL < 4) +#define DEBUG_TRACE(s, ...) +#else +#define DEBUG_TRACE(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif +#endif + +#ifdef CONFIG_NF_FLOW_COOKIE +typedef int (*flow_cookie_set_func_t)(u32 protocol, __be32 src_ip, __be16 src_port, + __be32 dst_ip, __be16 dst_port, u16 flow_cookie); +/* + * sfe_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb); + +/* + * sfe_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb); + +typedef int (*sfe_ipv6_flow_cookie_set_func_t)(u32 protocol, __be32 src_ip[4], __be16 src_port, + __be32 dst_ip[4], __be16 dst_port, u16 flow_cookie); + +/* + * sfe_ipv6_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); + +/* + * sfe_ipv6_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb); + +#endif /*CONFIG_NF_FLOW_COOKIE*/ diff --git a/shortcut-fe/src/sfe_backport.h b/shortcut-fe/src/sfe_backport.h new file mode 100644 index 000000000..2f8c8ca3c --- /dev/null +++ b/shortcut-fe/src/sfe_backport.h @@ -0,0 +1,195 @@ +/* + * sfe_backport.h + * Shortcut forwarding engine compatible header file. + * + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +#include +#else +enum udp_conntrack { + UDP_CT_UNREPLIED, + UDP_CT_REPLIED, + UDP_CT_MAX +}; + +static inline unsigned int * +nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct, + struct nf_conntrack_l4proto *l4proto) +{ +#ifdef CONFIG_NF_CONNTRACK_TIMEOUT + struct nf_conn_timeout *timeout_ext; + unsigned int *timeouts; + + timeout_ext = nf_ct_timeout_find(ct); + if (timeout_ext) + timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); + else + timeouts = l4proto->get_timeouts(net); + + return timeouts; +#else + return l4proto->get_timeouts(net); +#endif /*CONFIG_NF_CONNTRACK_TIMEOUT*/ +} +#endif /*KERNEL_VERSION(3, 7, 0)*/ +#endif /*KERNEL_VERSION(3, 4, 0)*/ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(void *priv, \ + struct sk_buff *SKB, \ + const struct nf_hook_state *state) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(const struct nf_hook_ops *OPS, \ + struct sk_buff *SKB, \ + const struct net_device *UNUSED, \ + const struct net_device *OUT, \ + int (*OKFN)(struct sk_buff *)) +#else +#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ +static unsigned int FN_NAME(unsigned int HOOKNUM, \ + struct sk_buff *SKB, \ + const struct net_device *UNUSED, \ + const struct net_device *OUT, \ + int (*OKFN)(struct sk_buff *)) +#endif + +#define sfe_cm_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__sfe_cm_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define sfe_cm_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__sfe_cm_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define fast_classifier_ipv4_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__fast_classifier_ipv4_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) +#define fast_classifier_ipv6_post_routing_hook(HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \ + sfe_define_post_routing_hook(__fast_classifier_ipv6_post_routing_hook, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .pf = NFPROTO_IPV4, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#else +#define SFE_IPV4_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .owner = THIS_MODULE, \ + .pf = NFPROTO_IPV4, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .pf = NFPROTO_IPV6, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP_PRI_NAT_SRC + 1, \ + } +#else +#define SFE_IPV6_NF_POST_ROUTING_HOOK(fn) \ + { \ + .hook = fn, \ + .owner = THIS_MODULE, \ + .pf = NFPROTO_IPV6, \ + .hooknum = NF_INET_POST_ROUTING, \ + .priority = NF_IP6_PRI_NAT_SRC + 1, \ + } +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) +#define SFE_NF_CT_DEFAULT_ZONE (&nf_ct_zone_dflt) +#else +#define SFE_NF_CT_DEFAULT_ZONE NF_CT_DEFAULT_ZONE +#endif + +/* + * sfe_dev_get_master + * get master of bridge port, and hold it + */ +static inline struct net_device *sfe_dev_get_master(struct net_device *dev) +{ + struct net_device *master; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) + rcu_read_lock(); + master = netdev_master_upper_dev_get_rcu(dev); + if (master) + dev_hold(master); + + rcu_read_unlock(); +#else + master = dev->master; + if (master) + dev_hold(master); +#endif + return master; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) +#define SFE_DEV_EVENT_PTR(PTR) netdev_notifier_info_to_dev(PTR) +#else +#define SFE_DEV_EVENT_PTR(PTR) (struct net_device *)(PTR) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define SFE_NF_CONN_ACCT(NM) struct nf_conn_acct *NM +#else +#define SFE_NF_CONN_ACCT(NM) struct nf_conn_counter *NM +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) +#define SFE_ACCT_COUNTER(NM) ((NM)->counter) +#else +#define SFE_ACCT_COUNTER(NM) (NM) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +#define sfe_hash_for_each_possible(name, obj, node, member, key) \ + hash_for_each_possible(name, obj, member, key) +#else +#define sfe_hash_for_each_possible(name, obj, node, member, key) \ + hash_for_each_possible(name, obj, node, member, key) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +#define sfe_hash_for_each(name, bkt, node, obj, member) \ + hash_for_each(name, bkt, obj, member) +#else +#define sfe_hash_for_each(name, bkt, node, obj, member) \ + hash_for_each(name, bkt, node, obj, member) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) +#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, daddr) +#else +static inline struct neighbour * +sfe_dst_get_neighbour(struct dst_entry *dst, void *daddr) +{ + struct neighbour *neigh = dst_get_neighbour_noref(dst); + + if (neigh) + neigh_hold(neigh); + + return neigh; +} +#endif diff --git a/shortcut-fe/src/sfe_cm.c b/shortcut-fe/src/sfe_cm.c new file mode 100644 index 000000000..18f3475e5 --- /dev/null +++ b/shortcut-fe/src/sfe_cm.c @@ -0,0 +1,1146 @@ +/* + * sfe-cm.c + * Shortcut forwarding engine connection manager. + * + * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sfe.h" +#include "sfe_cm.h" +#include "sfe_backport.h" + +typedef enum sfe_cm_exception { + SFE_CM_EXCEPTION_PACKET_BROADCAST, + SFE_CM_EXCEPTION_PACKET_MULTICAST, + SFE_CM_EXCEPTION_NO_IIF, + SFE_CM_EXCEPTION_NO_CT, + SFE_CM_EXCEPTION_CT_NO_TRACK, + SFE_CM_EXCEPTION_CT_NO_CONFIRM, + SFE_CM_EXCEPTION_CT_IS_ALG, + SFE_CM_EXCEPTION_IS_IPV4_MCAST, + SFE_CM_EXCEPTION_IS_IPV6_MCAST, + SFE_CM_EXCEPTION_TCP_NOT_ASSURED, + SFE_CM_EXCEPTION_TCP_NOT_ESTABLISHED, + SFE_CM_EXCEPTION_UNKNOW_PROTOCOL, + SFE_CM_EXCEPTION_NO_SRC_DEV, + SFE_CM_EXCEPTION_NO_SRC_XLATE_DEV, + SFE_CM_EXCEPTION_NO_DEST_DEV, + SFE_CM_EXCEPTION_NO_DEST_XLATE_DEV, + SFE_CM_EXCEPTION_NO_BRIDGE, + SFE_CM_EXCEPTION_LOCAL_OUT, + SFE_CM_EXCEPTION_MAX +} sfe_cm_exception_t; + +static char *sfe_cm_exception_events_string[SFE_CM_EXCEPTION_MAX] = { + "PACKET_BROADCAST", + "PACKET_MULTICAST", + "NO_IIF", + "NO_CT", + "CT_NO_TRACK", + "CT_NO_CONFIRM", + "CT_IS_ALG", + "IS_IPV4_MCAST", + "IS_IPV6_MCAST", + "TCP_NOT_ASSURED", + "TCP_NOT_ESTABLISHED", + "UNKNOW_PROTOCOL", + "NO_SRC_DEV", + "NO_SRC_XLATE_DEV", + "NO_DEST_DEV", + "NO_DEST_XLATE_DEV", + "NO_BRIDGE", + "LOCAL_OUT" +}; + +/* + * Per-module structure. + */ +struct sfe_cm { + spinlock_t lock; /* Lock for SMP correctness */ + + /* + * Control state. + */ + struct kobject *sys_sfe_cm; /* sysfs linkage */ + + /* + * Callback notifiers. + */ + struct notifier_block dev_notifier; /* Device notifier */ + struct notifier_block inet_notifier; /* IPv4 notifier */ + struct notifier_block inet6_notifier; /* IPv6 notifier */ + u32 exceptions[SFE_CM_EXCEPTION_MAX]; +}; + +static struct sfe_cm __sc; + +/* + * sfe_cm_incr_exceptions() + * increase an exception counter. + */ +static inline void sfe_cm_incr_exceptions(sfe_cm_exception_t except) +{ + struct sfe_cm *sc = &__sc; + + spin_lock_bh(&sc->lock); + sc->exceptions[except]++; + spin_unlock_bh(&sc->lock); +} + +/* + * sfe_cm_recv() + * Handle packet receives. + * + * Returns 1 if the packet is forwarded or 0 if it isn't. + */ +int sfe_cm_recv(struct sk_buff *skb) +{ + struct net_device *dev; + + /* + * We know that for the vast majority of packets we need the transport + * layer header so we may as well start to fetch it now! + */ + prefetch(skb->data + 32); + barrier(); + + dev = skb->dev; + + /* + * We're only interested in IPv4 and IPv6 packets. + */ + if (likely(htons(ETH_P_IP) == skb->protocol)) { + struct in_device *in_dev; + + /* + * Does our input device support IP processing? + */ + in_dev = (struct in_device *)dev->ip_ptr; + if (unlikely(!in_dev)) { + DEBUG_TRACE("no IP processing for device: %s\n", dev->name); + return 0; + } + + /* + * Does it have an IP address? If it doesn't then we can't do anything + * interesting here! + */ + if (unlikely(!in_dev->ifa_list)) { + DEBUG_TRACE("no IP address for device: %s\n", dev->name); + return 0; + } + + return sfe_ipv4_recv(dev, skb); + } + + if (likely(htons(ETH_P_IPV6) == skb->protocol)) { + struct inet6_dev *in_dev; + + /* + * Does our input device support IPv6 processing? + */ + in_dev = (struct inet6_dev *)dev->ip6_ptr; + if (unlikely(!in_dev)) { + DEBUG_TRACE("no IPv6 processing for device: %s\n", dev->name); + return 0; + } + + /* + * Does it have an IPv6 address? If it doesn't then we can't do anything + * interesting here! + */ + if (unlikely(list_empty(&in_dev->addr_list))) { + DEBUG_TRACE("no IPv6 address for device: %s\n", dev->name); + return 0; + } + + return sfe_ipv6_recv(dev, skb); + } + + DEBUG_TRACE("not IP packet\n"); + return 0; +} + +/* + * sfe_cm_find_dev_and_mac_addr() + * Find the device and MAC address for a given IPv4/IPv6 address. + * + * Returns true if we find the device and MAC address, otherwise false. + * + * We look up the rtable entry for the address and, from its neighbour + * structure, obtain the hardware address. This means this function also + * works if the neighbours are routers too. + */ +static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, int is_v4) +{ + struct neighbour *neigh; + struct rtable *rt; + struct rt6_info *rt6; + struct dst_entry *dst; + struct net_device *mac_dev; + + /* + * Look up the rtable entry for the IP address then get the hardware + * address from its neighbour structure. This means this work when the + * neighbours are routers too. + */ + if (likely(is_v4)) { + rt = ip_route_output(&init_net, addr->ip, 0, 0, 0); + if (unlikely(IS_ERR(rt))) { + goto ret_fail; + } + + dst = (struct dst_entry *)rt; + } else { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0); +#else + rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0); +#endif /*KERNEL_VERSION(4, 17, 0)*/ + if (!rt6) { + goto ret_fail; + } + + dst = (struct dst_entry *)rt6; + } + + rcu_read_lock(); + neigh = sfe_dst_get_neighbour(dst, addr); + if (unlikely(!neigh)) { + rcu_read_unlock(); + dst_release(dst); + goto ret_fail; + } + + if (unlikely(!(neigh->nud_state & NUD_VALID))) { + rcu_read_unlock(); + neigh_release(neigh); + dst_release(dst); + goto ret_fail; + } + + mac_dev = neigh->dev; + if (!mac_dev) { + rcu_read_unlock(); + neigh_release(neigh); + dst_release(dst); + goto ret_fail; + } + + memcpy(mac_addr, neigh->ha, (size_t)mac_dev->addr_len); + + dev_hold(mac_dev); + *dev = mac_dev; + rcu_read_unlock(); + neigh_release(neigh); + dst_release(dst); + + return true; + +ret_fail: + if (is_v4) { + DEBUG_TRACE("failed to find MAC address for IP: %pI4\n", &addr->ip); + + } else { + DEBUG_TRACE("failed to find MAC address for IP: %pI6\n", addr->ip6); + } + + return false; +} + +/* + * sfe_cm_post_routing() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) +{ + struct sfe_connection_create sic; + struct net_device *in; + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + struct net_device *dev; + struct net_device *src_dev; + struct net_device *dest_dev; + struct net_device *src_dev_tmp; + struct net_device *dest_dev_tmp; + struct net_device *src_br_dev = NULL; + struct net_device *dest_br_dev = NULL; + struct nf_conntrack_tuple orig_tuple; + struct nf_conntrack_tuple reply_tuple; + SFE_NF_CONN_ACCT(acct); + + /* + * Don't process broadcast or multicast packets. + */ + if (unlikely(skb->pkt_type == PACKET_BROADCAST)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_PACKET_BROADCAST); + DEBUG_TRACE("broadcast, ignoring\n"); + return NF_ACCEPT; + } + if (unlikely(skb->pkt_type == PACKET_MULTICAST)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_PACKET_MULTICAST); + DEBUG_TRACE("multicast, ignoring\n"); + return NF_ACCEPT; + } + +#ifdef CONFIG_XFRM + /* + * Packet to xfrm for encapsulation, we can't process it + */ + if (unlikely(skb_dst(skb)->xfrm)) { + DEBUG_TRACE("packet to xfrm, ignoring\n"); + return NF_ACCEPT; + } +#endif + + /* + * Don't process locally generated packets. + */ + if (skb->sk) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_LOCAL_OUT); + DEBUG_TRACE("skip local out packet\n"); + return NF_ACCEPT; + } + + /* + * Don't process packets that are not being forwarded. + */ + in = dev_get_by_index(&init_net, skb->skb_iif); + if (!in) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_IIF); + DEBUG_TRACE("packet not forwarding\n"); + return NF_ACCEPT; + } + + dev_put(in); + + /* + * Don't process packets that aren't being tracked by conntrack. + */ + ct = nf_ct_get(skb, &ctinfo); + if (unlikely(!ct)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_CT); + DEBUG_TRACE("no conntrack connection, ignoring\n"); + return NF_ACCEPT; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + /* + * Don't process untracked connections. + */ + if (unlikely(nf_ct_is_untracked(ct))) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_NO_TRACK); + DEBUG_TRACE("untracked connection\n"); + return NF_ACCEPT; + } +#endif /*KERNEL_VERSION(4, 12, 0)*/ + + /* + * Unconfirmed connection may be dropped by Linux at the final step, + * So we don't process unconfirmed connections. + */ + if (!nf_ct_is_confirmed(ct)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_NO_CONFIRM); + DEBUG_TRACE("unconfirmed connection\n"); + return NF_ACCEPT; + } + + /* + * Don't process connections that require support from a 'helper' (typically a NAT ALG). + */ + if (unlikely(nfct_help(ct))) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_CT_IS_ALG); + DEBUG_TRACE("connection has helper\n"); + return NF_ACCEPT; + } + + /* + * Check if the acceleration of a flow could be rejected quickly. + */ + acct = nf_conn_acct_find(ct); + if (acct) { + long long packets = atomic64_read(&SFE_ACCT_COUNTER(acct)[CTINFO2DIR(ctinfo)].packets); + if ((packets > 0xff) && (packets & 0xff)) { + /* + * Connection hits slow path at least 256 times, so it must be not able to accelerate. + * But we also give it a chance to walk through ECM every 256 packets + */ + return NF_ACCEPT; + } + } + + /* + * Look up the details of our connection in conntrack. + * + * Note that the data we get from conntrack is for the "ORIGINAL" direction + * but our packet may actually be in the "REPLY" direction. + */ + orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + reply_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; + sic.protocol = (s32)orig_tuple.dst.protonum; + + sic.flags = 0; + + /* + * Get addressing information, non-NAT first + */ + if (likely(is_v4)) { + u32 dscp; + + sic.src_ip.ip = (__be32)orig_tuple.src.u3.ip; + sic.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; + + if (ipv4_is_multicast(sic.src_ip.ip) || ipv4_is_multicast(sic.dest_ip.ip)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_IS_IPV4_MCAST); + DEBUG_TRACE("multicast address\n"); + return NF_ACCEPT; + } + + /* + * NAT'ed addresses - note these are as seen from the 'reply' direction + * When NAT does not apply to this connection these will be identical to the above. + */ + sic.src_ip_xlate.ip = (__be32)reply_tuple.dst.u3.ip; + sic.dest_ip_xlate.ip = (__be32)reply_tuple.src.u3.ip; + + dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; + if (dscp) { + sic.dest_dscp = dscp; + sic.src_dscp = sic.dest_dscp; + sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; + } + } else { + u32 dscp; + + sic.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); + sic.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); + + if (ipv6_addr_is_multicast((struct in6_addr *)sic.src_ip.ip6) || + ipv6_addr_is_multicast((struct in6_addr *)sic.dest_ip.ip6)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_IS_IPV6_MCAST); + DEBUG_TRACE("multicast address\n"); + return NF_ACCEPT; + } + + /* + * NAT'ed addresses - note these are as seen from the 'reply' direction + * When NAT does not apply to this connection these will be identical to the above. + */ + sic.src_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.dst.u3.in6); + sic.dest_ip_xlate.ip6[0] = *((struct sfe_ipv6_addr *)&reply_tuple.src.u3.in6); + + dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; + if (dscp) { + sic.dest_dscp = dscp; + sic.src_dscp = sic.dest_dscp; + sic.flags |= SFE_CREATE_FLAG_REMARK_DSCP; + } + } + + switch (sic.protocol) { + case IPPROTO_TCP: + sic.src_port = orig_tuple.src.u.tcp.port; + sic.dest_port = orig_tuple.dst.u.tcp.port; + sic.src_port_xlate = reply_tuple.dst.u.tcp.port; + sic.dest_port_xlate = reply_tuple.src.u.tcp.port; + sic.src_td_window_scale = ct->proto.tcp.seen[0].td_scale; + sic.src_td_max_window = ct->proto.tcp.seen[0].td_maxwin; + sic.src_td_end = ct->proto.tcp.seen[0].td_end; + sic.src_td_max_end = ct->proto.tcp.seen[0].td_maxend; + sic.dest_td_window_scale = ct->proto.tcp.seen[1].td_scale; + sic.dest_td_max_window = ct->proto.tcp.seen[1].td_maxwin; + sic.dest_td_end = ct->proto.tcp.seen[1].td_end; + sic.dest_td_max_end = ct->proto.tcp.seen[1].td_maxend; + + if (nf_ct_tcp_no_window_check + || (ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_BE_LIBERAL) + || (ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_BE_LIBERAL)) { + sic.flags |= SFE_CREATE_FLAG_NO_SEQ_CHECK; + } + + /* + * Don't try to manage a non-established connection. + */ + if (!test_bit(IPS_ASSURED_BIT, &ct->status)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_TCP_NOT_ASSURED); + DEBUG_TRACE("non-established connection\n"); + return NF_ACCEPT; + } + + /* + * If the connection is shutting down do not manage it. + * state can not be SYN_SENT, SYN_RECV because connection is assured + * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. + */ + spin_lock_bh(&ct->lock); + if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) { + spin_unlock_bh(&ct->lock); + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_TCP_NOT_ESTABLISHED); + DEBUG_TRACE("connection in termination state: %#x, s: %pI4:%u, d: %pI4:%u\n", + ct->proto.tcp.state, &sic.src_ip, ntohs(sic.src_port), + &sic.dest_ip, ntohs(sic.dest_port)); + return NF_ACCEPT; + } + spin_unlock_bh(&ct->lock); + break; + + case IPPROTO_UDP: + sic.src_port = orig_tuple.src.u.udp.port; + sic.dest_port = orig_tuple.dst.u.udp.port; + sic.src_port_xlate = reply_tuple.dst.u.udp.port; + sic.dest_port_xlate = reply_tuple.src.u.udp.port; + break; + + default: + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_UNKNOW_PROTOCOL); + DEBUG_TRACE("unhandled protocol %d\n", sic.protocol); + return NF_ACCEPT; + } + +#ifdef CONFIG_XFRM + sic.original_accel = 1; + sic.reply_accel = 1; + + /* + * For packets de-capsulated from xfrm, we still can accelerate it + * on the direction we just received the packet. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) + if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) { +#else + if (unlikely(skb->sp)) { +#endif + if (sic.protocol == IPPROTO_TCP && + !(sic.flags & SFE_CREATE_FLAG_NO_SEQ_CHECK)) { + return NF_ACCEPT; + } + + if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { + sic.reply_accel = 0; + } else { + sic.original_accel = 0; + } + } +#endif + + /* + * Get QoS information + */ + if (skb->priority) { + sic.dest_priority = skb->priority; + sic.src_priority = sic.dest_priority; + sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY; + } + + /* + * Get the net device and MAC addresses that correspond to the various source and + * destination host addresses. + */ + if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_DEV); + return NF_ACCEPT; + } + src_dev = src_dev_tmp; + + if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_XLATE_DEV); + goto done1; + } + dev_put(dev); + + if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip, &dev, sic.dest_mac, is_v4)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_DEV); + goto done1; + } + dev_put(dev); + + if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_XLATE_DEV); + goto done1; + } + dest_dev = dest_dev_tmp; + + /* + * Our devices may actually be part of a bridge interface. If that's + * the case then find the bridge interface instead. + */ + if (src_dev->priv_flags & IFF_BRIDGE_PORT) { + src_br_dev = sfe_dev_get_master(src_dev); + if (!src_br_dev) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_BRIDGE); + DEBUG_TRACE("no bridge found for: %s\n", src_dev->name); + goto done2; + } + src_dev = src_br_dev; + } + + if (dest_dev->priv_flags & IFF_BRIDGE_PORT) { + dest_br_dev = sfe_dev_get_master(dest_dev); + if (!dest_br_dev) { + sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_BRIDGE); + DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name); + goto done3; + } + dest_dev = dest_br_dev; + } + + sic.src_dev = src_dev; + sic.dest_dev = dest_dev; + + sic.src_mtu = src_dev->mtu; + sic.dest_mtu = dest_dev->mtu; + + if (likely(is_v4)) { + sfe_ipv4_create_rule(&sic); + } else { + sfe_ipv6_create_rule(&sic); + } + + /* + * If we had bridge ports then release them too. + */ + if (dest_br_dev) { + dev_put(dest_br_dev); + } +done3: + if (src_br_dev) { + dev_put(src_br_dev); + } +done2: + dev_put(dest_dev_tmp); +done1: + dev_put(src_dev_tmp); + + return NF_ACCEPT; +} + +/* + * sfe_cm_ipv4_post_routing_hook() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +sfe_cm_ipv4_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) +{ + return sfe_cm_post_routing(skb, true); +} + +/* + * sfe_cm_ipv6_post_routing_hook() + * Called for packets about to leave the box - either locally generated or forwarded from another interface + */ +sfe_cm_ipv6_post_routing_hook(hooknum, ops, skb, in_unused, out, okfn) +{ + return sfe_cm_post_routing(skb, false); +} + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +/* + * sfe_cm_conntrack_event() + * Callback event invoked when a conntrack connection's state changes. + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +static int sfe_cm_conntrack_event(struct notifier_block *this, + unsigned long events, void *ptr) +#else +static int sfe_cm_conntrack_event(unsigned int events, struct nf_ct_event *item) +#endif +{ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + struct nf_ct_event *item = ptr; +#endif + struct sfe_connection_destroy sid; + struct nf_conn *ct = item->ct; + struct nf_conntrack_tuple orig_tuple; + + /* + * If we don't have a conntrack entry then we're done. + */ + if (unlikely(!ct)) { + DEBUG_WARN("no ct in conntrack event callback\n"); + return NOTIFY_DONE; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) + /* + * If this is an untracked connection then we can't have any state either. + */ + if (unlikely(nf_ct_is_untracked(ct))) { + DEBUG_TRACE("ignoring untracked conn\n"); + return NOTIFY_DONE; + } +#endif /*KERNEL_VERSION(4, 12, 0)*/ + + /* + * We're only interested in destroy events. + */ + if (unlikely(!(events & (1 << IPCT_DESTROY)))) { + DEBUG_TRACE("ignoring non-destroy event\n"); + return NOTIFY_DONE; + } + + orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + sid.protocol = (s32)orig_tuple.dst.protonum; + + /* + * Extract information from the conntrack connection. We're only interested + * in nominal connection information (i.e. we're ignoring any NAT information). + */ + switch (sid.protocol) { + case IPPROTO_TCP: + sid.src_port = orig_tuple.src.u.tcp.port; + sid.dest_port = orig_tuple.dst.u.tcp.port; + break; + + case IPPROTO_UDP: + sid.src_port = orig_tuple.src.u.udp.port; + sid.dest_port = orig_tuple.dst.u.udp.port; + break; + + default: + DEBUG_TRACE("unhandled protocol: %d\n", sid.protocol); + return NOTIFY_DONE; + } + + if (likely(nf_ct_l3num(ct) == AF_INET)) { + sid.src_ip.ip = (__be32)orig_tuple.src.u3.ip; + sid.dest_ip.ip = (__be32)orig_tuple.dst.u3.ip; + + sfe_ipv4_destroy_rule(&sid); + } else if (likely(nf_ct_l3num(ct) == AF_INET6)) { + sid.src_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.src.u3.in6); + sid.dest_ip.ip6[0] = *((struct sfe_ipv6_addr *)&orig_tuple.dst.u3.in6); + + sfe_ipv6_destroy_rule(&sid); + } else { + DEBUG_TRACE("ignoring non-IPv4 and non-IPv6 connection\n"); + } + + return NOTIFY_DONE; +} + +/* + * Netfilter conntrack event system to monitor connection tracking changes + */ +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +static struct notifier_block sfe_cm_conntrack_notifier = { + .notifier_call = sfe_cm_conntrack_event, +}; +#else +static struct nf_ct_event_notifier sfe_cm_conntrack_notifier = { + .fcn = sfe_cm_conntrack_event, +}; +#endif +#endif + +/* + * Structure to establish a hook into the post routing netfilter point - this + * will pick up local outbound and packets going from one interface to another. + * + * Note: see include/linux/netfilter_ipv4.h for info related to priority levels. + * We want to examine packets after NAT translation and any ALG processing. + */ +static struct nf_hook_ops sfe_cm_ops_post_routing[] __read_mostly = { + SFE_IPV4_NF_POST_ROUTING_HOOK(__sfe_cm_ipv4_post_routing_hook), +#ifdef SFE_SUPPORT_IPV6 + SFE_IPV6_NF_POST_ROUTING_HOOK(__sfe_cm_ipv6_post_routing_hook), +#endif +}; + +/* + * sfe_cm_sync_rule() + * Synchronize a connection's state. + */ +static void sfe_cm_sync_rule(struct sfe_connection_sync *sis) +{ + struct nf_conntrack_tuple_hash *h; + struct nf_conntrack_tuple tuple; + struct nf_conn *ct; + SFE_NF_CONN_ACCT(acct); + + /* + * Create a tuple so as to be able to look up a connection + */ + memset(&tuple, 0, sizeof(tuple)); + tuple.src.u.all = (__be16)sis->src_port; + tuple.dst.dir = IP_CT_DIR_ORIGINAL; + tuple.dst.protonum = (u8)sis->protocol; + tuple.dst.u.all = (__be16)sis->dest_port; + + if (sis->is_v6) { + tuple.src.u3.in6 = *((struct in6_addr *)sis->src_ip.ip6); + tuple.dst.u3.in6 = *((struct in6_addr *)sis->dest_ip.ip6); + tuple.src.l3num = AF_INET6; + + DEBUG_TRACE("update connection - p: %d, s: %pI6:%u, d: %pI6:%u\n", + (int)tuple.dst.protonum, + &tuple.src.u3.in6, (unsigned int)ntohs(tuple.src.u.all), + &tuple.dst.u3.in6, (unsigned int)ntohs(tuple.dst.u.all)); + } else { + tuple.src.u3.ip = sis->src_ip.ip; + tuple.dst.u3.ip = sis->dest_ip.ip; + tuple.src.l3num = AF_INET; + + DEBUG_TRACE("update connection - p: %d, s: %pI4:%u, d: %pI4:%u\n", + (int)tuple.dst.protonum, + &tuple.src.u3.ip, (unsigned int)ntohs(tuple.src.u.all), + &tuple.dst.u3.ip, (unsigned int)ntohs(tuple.dst.u.all)); + } + + /* + * Look up conntrack connection + */ + h = nf_conntrack_find_get(&init_net, SFE_NF_CT_DEFAULT_ZONE, &tuple); + if (unlikely(!h)) { + DEBUG_TRACE("no connection found\n"); + return; + } + + ct = nf_ct_tuplehash_to_ctrack(h); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) + NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct); +#endif /*KERNEL_VERSION(4, 9, 0)*/ + + /* + * Only update if this is not a fixed timeout + */ + if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) { + spin_lock_bh(&ct->lock); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + ct->timeout += sis->delta_jiffies; +#else + ct->timeout.expires += sis->delta_jiffies; +#endif /*KERNEL_VERSION(4, 9, 0)*/ + spin_unlock_bh(&ct->lock); + } + + acct = nf_conn_acct_find(ct); + if (acct) { + spin_lock_bh(&ct->lock); + atomic64_add(sis->src_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].packets); + atomic64_add(sis->src_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_ORIGINAL].bytes); + atomic64_add(sis->dest_new_packet_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); + atomic64_add(sis->dest_new_byte_count, &SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].bytes); + spin_unlock_bh(&ct->lock); + } + + switch (sis->protocol) { + case IPPROTO_TCP: + spin_lock_bh(&ct->lock); + if (ct->proto.tcp.seen[0].td_maxwin < sis->src_td_max_window) { + ct->proto.tcp.seen[0].td_maxwin = sis->src_td_max_window; + } + if ((s32)(ct->proto.tcp.seen[0].td_end - sis->src_td_end) < 0) { + ct->proto.tcp.seen[0].td_end = sis->src_td_end; + } + if ((s32)(ct->proto.tcp.seen[0].td_maxend - sis->src_td_max_end) < 0) { + ct->proto.tcp.seen[0].td_maxend = sis->src_td_max_end; + } + if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) { + ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window; + } + if ((s32)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) { + ct->proto.tcp.seen[1].td_end = sis->dest_td_end; + } + if ((s32)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) { + ct->proto.tcp.seen[1].td_maxend = sis->dest_td_max_end; + } + spin_unlock_bh(&ct->lock); + break; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + case IPPROTO_UDP: + /* + * In Linux connection track, UDP flow has two timeout values: + * /proc/sys/net/netfilter/nf_conntrack_udp_timeout: + * this is for uni-direction UDP flow, normally its value is 60 seconds + * /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream: + * this is for bi-direction UDP flow, normally its value is 180 seconds + * + * Linux will update timer of UDP flow to stream timeout once it seen packets + * in reply direction. But if flow is accelerated by NSS or SFE, Linux won't + * see any packets. So we have to do the same thing in our stats sync message. + */ + if (!test_bit(IPS_ASSURED_BIT, &ct->status) && acct) { + u_int64_t reply_pkts = atomic64_read(&SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets); + + if (reply_pkts != 0) { + unsigned int *timeouts; + + set_bit(IPS_SEEN_REPLY_BIT, &ct->status); + set_bit(IPS_ASSURED_BIT, &ct->status); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) + timeouts = nf_ct_timeout_lookup(ct); +#else + struct nf_conntrack_l4proto *l4proto; + + l4proto = __nf_ct_l4proto_find((sis->is_v6 ? AF_INET6 : AF_INET), IPPROTO_UDP); + timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto); +#endif /*KERNEL_VERSION(4, 19, 0)*/ + + spin_lock_bh(&ct->lock); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) + ct->timeout = jiffies + timeouts[UDP_CT_REPLIED]; +#else + ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED]; +#endif /*KERNEL_VERSION(4, 9, 0)*/ + spin_unlock_bh(&ct->lock); + } + } + break; +#endif /*KERNEL_VERSION(3, 4, 0)*/ + } + + /* + * Release connection + */ + nf_ct_put(ct); +} + +/* + * sfe_cm_device_event() + */ +int sfe_cm_device_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = SFE_DEV_EVENT_PTR(ptr); + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv4_destroy_all_rules_for_dev(dev); + sfe_ipv6_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * sfe_cm_inet_event() + */ +static int sfe_cm_inet_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv4_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * sfe_cm_inet6_event() + */ +static int sfe_cm_inet6_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ((struct inet6_ifaddr *)ptr)->idev->dev; + + if (dev && (event == NETDEV_DOWN)) { + sfe_ipv6_destroy_all_rules_for_dev(dev); + } + + return NOTIFY_DONE; +} + +/* + * sfe_cm_get_exceptions + * dump exception counters + */ +static ssize_t sfe_cm_get_exceptions(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int idx, len; + struct sfe_cm *sc = &__sc; + + spin_lock_bh(&sc->lock); + for (len = 0, idx = 0; idx < SFE_CM_EXCEPTION_MAX; idx++) { + if (sc->exceptions[idx]) { + len += snprintf(buf + len, (ssize_t)(PAGE_SIZE - len), "%s = %d\n", sfe_cm_exception_events_string[idx], sc->exceptions[idx]); + } + } + spin_unlock_bh(&sc->lock); + + return len; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_cm_exceptions_attr = + __ATTR(exceptions, S_IRUGO, sfe_cm_get_exceptions, NULL); + +/* + * sfe_cm_init() + */ +static int __init sfe_cm_init(void) +{ + struct sfe_cm *sc = &__sc; + int result = -1; + + DEBUG_INFO("SFE CM init\n"); + + /* + * Create sys/sfe_cm + */ + sc->sys_sfe_cm = kobject_create_and_add("sfe_cm", NULL); + if (!sc->sys_sfe_cm) { + DEBUG_ERROR("failed to register sfe_cm\n"); + goto exit1; + } + + /* + * Create sys/sfe_cm/exceptions + */ + result = sysfs_create_file(sc->sys_sfe_cm, &sfe_cm_exceptions_attr.attr); + if (result) { + DEBUG_ERROR("failed to register exceptions file: %d\n", result); + goto exit2; + } + + sc->dev_notifier.notifier_call = sfe_cm_device_event; + sc->dev_notifier.priority = 1; + register_netdevice_notifier(&sc->dev_notifier); + + sc->inet_notifier.notifier_call = sfe_cm_inet_event; + sc->inet_notifier.priority = 1; + register_inetaddr_notifier(&sc->inet_notifier); + + sc->inet6_notifier.notifier_call = sfe_cm_inet6_event; + sc->inet6_notifier.priority = 1; + register_inet6addr_notifier(&sc->inet6_notifier); + /* + * Register our netfilter hooks. + */ + result = nf_register_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); + if (result < 0) { + DEBUG_ERROR("can't register nf post routing hook: %d\n", result); + goto exit3; + } + + /* + * Register a notifier hook to get fast notifications of expired connections. + * Note: In CONFIG_NF_CONNTRACK_CHAIN_EVENTS enabled case, nf_conntrack_register_notifier() + * function always returns 0. + */ +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + (void)nf_conntrack_register_chain_notifier(&init_net, &sfe_cm_conntrack_notifier); +#else + result = nf_conntrack_register_notifier(&init_net, &sfe_cm_conntrack_notifier); + if (result < 0) { + DEBUG_ERROR("can't register nf notifier hook: %d\n", result); + goto exit4; + } +#endif +#endif + + spin_lock_init(&sc->lock); + + /* + * Hook the receive path in the network stack. + */ + BUG_ON(athrs_fast_nat_recv); + RCU_INIT_POINTER(athrs_fast_nat_recv, sfe_cm_recv); + + /* + * Hook the shortcut sync callback. + */ + sfe_ipv4_register_sync_rule_callback(sfe_cm_sync_rule); + sfe_ipv6_register_sync_rule_callback(sfe_cm_sync_rule); + return 0; + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS +exit4: + nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); +#endif +#endif +exit3: + unregister_inet6addr_notifier(&sc->inet6_notifier); + unregister_inetaddr_notifier(&sc->inet_notifier); + unregister_netdevice_notifier(&sc->dev_notifier); +exit2: + kobject_put(sc->sys_sfe_cm); + +exit1: + return result; +} + +/* + * sfe_cm_exit() + */ +static void __exit sfe_cm_exit(void) +{ + struct sfe_cm *sc = &__sc; + + DEBUG_INFO("SFE CM exit\n"); + + /* + * Unregister our sync callback. + */ + sfe_ipv4_register_sync_rule_callback(NULL); + sfe_ipv6_register_sync_rule_callback(NULL); + + /* + * Unregister our receive callback. + */ + RCU_INIT_POINTER(athrs_fast_nat_recv, NULL); + + /* + * Wait for all callbacks to complete. + */ + rcu_barrier(); + + /* + * Destroy all connections. + */ + sfe_ipv4_destroy_all_rules_for_dev(NULL); + sfe_ipv6_destroy_all_rules_for_dev(NULL); + +#ifdef CONFIG_NF_CONNTRACK_EVENTS +#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS + nf_conntrack_unregister_chain_notifier(&init_net, &sfe_cm_conntrack_notifier); +#else + nf_conntrack_unregister_notifier(&init_net, &sfe_cm_conntrack_notifier); +#endif +#endif + nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing)); + + unregister_inet6addr_notifier(&sc->inet6_notifier); + unregister_inetaddr_notifier(&sc->inet_notifier); + unregister_netdevice_notifier(&sc->dev_notifier); + + kobject_put(sc->sys_sfe_cm); +} + +module_init(sfe_cm_init) +module_exit(sfe_cm_exit) + +MODULE_DESCRIPTION("Shortcut Forwarding Engine - Connection Manager"); +MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/shortcut-fe/src/sfe_cm.h b/shortcut-fe/src/sfe_cm.h new file mode 100644 index 000000000..23cbde859 --- /dev/null +++ b/shortcut-fe/src/sfe_cm.h @@ -0,0 +1,259 @@ +/* + * sfe_cm.h + * Shortcut forwarding engine. + * + * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * connection flags. + */ +#define SFE_CREATE_FLAG_NO_SEQ_CHECK BIT(0) + /* Indicates that we should not check sequence numbers */ +#define SFE_CREATE_FLAG_REMARK_PRIORITY BIT(1) + /* Indicates that we should remark priority of skb */ +#define SFE_CREATE_FLAG_REMARK_DSCP BIT(2) + /* Indicates that we should remark DSCP of packet */ + +/* + * IPv6 address structure + */ +struct sfe_ipv6_addr { + __be32 addr[4]; +}; + +typedef union { + __be32 ip; + struct sfe_ipv6_addr ip6[1]; +} sfe_ip_addr_t; + +/* + * connection creation structure. + */ +struct sfe_connection_create { + int protocol; + struct net_device *src_dev; + struct net_device *dest_dev; + u32 flags; + u32 src_mtu; + u32 dest_mtu; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t src_ip_xlate; + sfe_ip_addr_t dest_ip; + sfe_ip_addr_t dest_ip_xlate; + __be16 src_port; + __be16 src_port_xlate; + __be16 dest_port; + __be16 dest_port_xlate; + u8 src_mac[ETH_ALEN]; + u8 src_mac_xlate[ETH_ALEN]; + u8 dest_mac[ETH_ALEN]; + u8 dest_mac_xlate[ETH_ALEN]; + u8 src_td_window_scale; + u32 src_td_max_window; + u32 src_td_end; + u32 src_td_max_end; + u8 dest_td_window_scale; + u32 dest_td_max_window; + u32 dest_td_end; + u32 dest_td_max_end; + u32 mark; +#ifdef CONFIG_XFRM + u32 original_accel; + u32 reply_accel; +#endif + u32 src_priority; + u32 dest_priority; + u32 src_dscp; + u32 dest_dscp; +}; + +/* + * connection destruction structure. + */ +struct sfe_connection_destroy { + int protocol; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t dest_ip; + __be16 src_port; + __be16 dest_port; +}; + +typedef enum sfe_sync_reason { + SFE_SYNC_REASON_STATS, /* Sync is to synchronize stats */ + SFE_SYNC_REASON_FLUSH, /* Sync is to flush a entry */ + SFE_SYNC_REASON_DESTROY /* Sync is to destroy a entry(requested by connection manager) */ +} sfe_sync_reason_t; + +/* + * Structure used to sync connection stats/state back within the system. + * + * NOTE: The addresses here are NON-NAT addresses, i.e. the true endpoint addressing. + * 'src' is the creator of the connection. + */ +struct sfe_connection_sync { + struct net_device *src_dev; + struct net_device *dest_dev; + int is_v6; /* Is it for ipv6? */ + int protocol; /* IP protocol number (IPPROTO_...) */ + sfe_ip_addr_t src_ip; /* Non-NAT source address, i.e. the creator of the connection */ + sfe_ip_addr_t src_ip_xlate; /* NATed source address */ + __be16 src_port; /* Non-NAT source port */ + __be16 src_port_xlate; /* NATed source port */ + sfe_ip_addr_t dest_ip; /* Non-NAT destination address, i.e. to whom the connection was created */ + sfe_ip_addr_t dest_ip_xlate; /* NATed destination address */ + __be16 dest_port; /* Non-NAT destination port */ + __be16 dest_port_xlate; /* NATed destination port */ + u32 src_td_max_window; + u32 src_td_end; + u32 src_td_max_end; + u64 src_packet_count; + u64 src_byte_count; + u32 src_new_packet_count; + u32 src_new_byte_count; + u32 dest_td_max_window; + u32 dest_td_end; + u32 dest_td_max_end; + u64 dest_packet_count; + u64 dest_byte_count; + u32 dest_new_packet_count; + u32 dest_new_byte_count; + u32 reason; /* reason for stats sync message, i.e. destroy, flush, period sync */ + u64 delta_jiffies; /* Time to be added to the current timeout to keep the connection alive */ +}; + +/* + * connection mark structure + */ +struct sfe_connection_mark { + int protocol; + sfe_ip_addr_t src_ip; + sfe_ip_addr_t dest_ip; + __be16 src_port; + __be16 dest_port; + u32 mark; +}; + +/* + * Expose the hook for the receive processing. + */ +extern int (*athrs_fast_nat_recv)(struct sk_buff *skb); + +/* + * Expose what should be a static flag in the TCP connection tracker. + */ +extern int nf_ct_tcp_no_window_check; + +/* + * This callback will be called in a timer + * at 100 times per second to sync stats back to + * Linux connection track. + * + * A RCU lock is taken to prevent this callback + * from unregistering. + */ +typedef void (*sfe_sync_rule_callback_t)(struct sfe_connection_sync *); + +/* + * IPv4 APIs used by connection manager + */ +int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb); +int sfe_ipv4_create_rule(struct sfe_connection_create *sic); +void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid); +void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev); +void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t callback); +void sfe_ipv4_update_rule(struct sfe_connection_create *sic); +void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark); + +#ifdef SFE_SUPPORT_IPV6 +/* + * IPv6 APIs used by connection manager + */ +int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb); +int sfe_ipv6_create_rule(struct sfe_connection_create *sic); +void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid); +void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev); +void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback); +void sfe_ipv6_update_rule(struct sfe_connection_create *sic); +void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark); +#else +static inline int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) +{ + return 0; +} + +static inline int sfe_ipv6_create_rule(struct sfe_connection_create *sic) +{ + return 0; +} + +static inline void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid) +{ + return; +} + +static inline void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev) +{ + return; +} + +static inline void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback) +{ + return; +} + +static inline void sfe_ipv6_update_rule(struct sfe_connection_create *sic) +{ + return; +} + +static inline void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark) +{ + return; +} +#endif + +/* + * sfe_ipv6_addr_equal() + * compare ipv6 address + * + * return: 1, equal; 0, no equal + */ +static inline int sfe_ipv6_addr_equal(struct sfe_ipv6_addr *a, + struct sfe_ipv6_addr *b) +{ + return a->addr[0] == b->addr[0] && + a->addr[1] == b->addr[1] && + a->addr[2] == b->addr[2] && + a->addr[3] == b->addr[3]; +} + +/* + * sfe_ipv4_addr_equal() + * compare ipv4 address + * + * return: 1, equal; 0, no equal + */ +#define sfe_ipv4_addr_equal(a, b) ((u32)(a) == (u32)(b)) + +/* + * sfe_addr_equal() + * compare ipv4 or ipv6 address + * + * return: 1, equal; 0, no equal + */ +static inline int sfe_addr_equal(sfe_ip_addr_t *a, + sfe_ip_addr_t *b, int is_v4) +{ + return is_v4 ? sfe_ipv4_addr_equal(a->ip, b->ip) : sfe_ipv6_addr_equal(a->ip6, b->ip6); +} diff --git a/shortcut-fe/src/sfe_ipv4.c b/shortcut-fe/src/sfe_ipv4.c new file mode 100644 index 000000000..531456c05 --- /dev/null +++ b/shortcut-fe/src/sfe_ipv4.c @@ -0,0 +1,3621 @@ +/* + * sfe_ipv4.c + * Shortcut forwarding engine - IPv4 edition. + * + * Copyright (c) 2013-2016, 2019, The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sfe.h" +#include "sfe_cm.h" + +/* + * By default Linux IP header and transport layer header structures are + * unpacked, assuming that such headers should be 32-bit aligned. + * Unfortunately some wireless adaptors can't cope with this requirement and + * some CPUs can't handle misaligned accesses. For those platforms we + * define SFE_IPV4_UNALIGNED_IP_HEADER and mark the structures as packed. + * When we do this the compiler will generate slightly worse code than for the + * aligned case (on most platforms) but will be much quicker than fixing + * things up in an unaligned trap handler. + */ +#define SFE_IPV4_UNALIGNED_IP_HEADER 1 +#if SFE_IPV4_UNALIGNED_IP_HEADER +#define SFE_IPV4_UNALIGNED_STRUCT __attribute__((packed)) +#else +#define SFE_IPV4_UNALIGNED_STRUCT +#endif + +/* + * An Ethernet header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV4_UNALIGNED_STRUCT) + */ +struct sfe_ipv4_eth_hdr { + __be16 h_dest[ETH_ALEN / 2]; + __be16 h_source[ETH_ALEN / 2]; + __be16 h_proto; +} SFE_IPV4_UNALIGNED_STRUCT; + +#define SFE_IPV4_DSCP_MASK 0x3 +#define SFE_IPV4_DSCP_SHIFT 2 + +/* + * An IPv4 header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV4_UNALIGNED_STRUCT) + */ +struct sfe_ipv4_ip_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 ihl:4, + version:4; +#elif defined (__BIG_ENDIAN_BITFIELD) + __u8 version:4, + ihl:4; +#else +#error "Please fix " +#endif + __u8 tos; + __be16 tot_len; + __be16 id; + __be16 frag_off; + __u8 ttl; + __u8 protocol; + __sum16 check; + __be32 saddr; + __be32 daddr; + + /* + * The options start here. + */ +} SFE_IPV4_UNALIGNED_STRUCT; + +/* + * A UDP header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV4_UNALIGNED_STRUCT) + */ +struct sfe_ipv4_udp_hdr { + __be16 source; + __be16 dest; + __be16 len; + __sum16 check; +} SFE_IPV4_UNALIGNED_STRUCT; + +/* + * A TCP header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV4_UNALIGNED_STRUCT) + */ +struct sfe_ipv4_tcp_hdr { + __be16 source; + __be16 dest; + __be32 seq; + __be32 ack_seq; +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 res1:4, + doff:4, + fin:1, + syn:1, + rst:1, + psh:1, + ack:1, + urg:1, + ece:1, + cwr:1; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u16 doff:4, + res1:4, + cwr:1, + ece:1, + urg:1, + ack:1, + psh:1, + rst:1, + syn:1, + fin:1; +#else +#error "Adjust your defines" +#endif + __be16 window; + __sum16 check; + __be16 urg_ptr; +} SFE_IPV4_UNALIGNED_STRUCT; + +/* + * Specifies the lower bound on ACK numbers carried in the TCP header + */ +#define SFE_IPV4_TCP_MAX_ACK_WINDOW 65520 + +/* + * IPv4 TCP connection match additional data. + */ +struct sfe_ipv4_tcp_connection_match { + u8 win_scale; /* Window scale */ + u32 max_win; /* Maximum window size seen */ + u32 end; /* Sequence number of the next byte to send (seq + segment length) */ + u32 max_end; /* Sequence number of the last byte to ack */ +}; + +/* + * Bit flags for IPv4 connection matching entry. + */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC (1<<0) + /* Perform source translation */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST (1<<1) + /* Perform destination translation */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK (1<<2) + /* Ignore TCP sequence numbers */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR (1<<3) + /* Fast Ethernet header write */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR (1<<4) + /* Fast Ethernet header write */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK (1<<5) + /* remark priority of SKB */ +#define SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK (1<<6) + /* remark DSCP of packet */ + +/* + * IPv4 connection matching structure. + */ +struct sfe_ipv4_connection_match { + /* + * References to other objects. + */ + struct sfe_ipv4_connection_match *next; + struct sfe_ipv4_connection_match *prev; + struct sfe_ipv4_connection *connection; + struct sfe_ipv4_connection_match *counter_match; + /* Matches the flow in the opposite direction as the one in *connection */ + struct sfe_ipv4_connection_match *active_next; + struct sfe_ipv4_connection_match *active_prev; + bool active; /* Flag to indicate if we're on the active list */ + + /* + * Characteristics that identify flows that match this rule. + */ + struct net_device *match_dev; /* Network device */ + u8 match_protocol; /* Protocol */ + __be32 match_src_ip; /* Source IP address */ + __be32 match_dest_ip; /* Destination IP address */ + __be16 match_src_port; /* Source port/connection ident */ + __be16 match_dest_port; /* Destination port/connection ident */ + + /* + * Control the operations of the match. + */ + u32 flags; /* Bit flags */ +#ifdef CONFIG_NF_FLOW_COOKIE + u32 flow_cookie; /* used flow cookie, for debug */ +#endif +#ifdef CONFIG_XFRM + u32 flow_accel; /* The flow accelerated or not */ +#endif + + /* + * Connection state that we track once we match. + */ + union { /* Protocol-specific state */ + struct sfe_ipv4_tcp_connection_match tcp; + } protocol_state; + /* + * Stats recorded in a sync period. These stats will be added to + * rx_packet_count64/rx_byte_count64 after a sync period. + */ + u32 rx_packet_count; + u32 rx_byte_count; + + /* + * Packet translation information. + */ + __be32 xlate_src_ip; /* Address after source translation */ + __be16 xlate_src_port; /* Port/connection ident after source translation */ + u16 xlate_src_csum_adjustment; + /* Transport layer checksum adjustment after source translation */ + u16 xlate_src_partial_csum_adjustment; + /* Transport layer pseudo header checksum adjustment after source translation */ + + __be32 xlate_dest_ip; /* Address after destination translation */ + __be16 xlate_dest_port; /* Port/connection ident after destination translation */ + u16 xlate_dest_csum_adjustment; + /* Transport layer checksum adjustment after destination translation */ + u16 xlate_dest_partial_csum_adjustment; + /* Transport layer pseudo header checksum adjustment after destination translation */ + + /* + * QoS information + */ + u32 priority; + u32 dscp; + + /* + * Packet transmit information. + */ + struct net_device *xmit_dev; /* Network device on which to transmit */ + unsigned short int xmit_dev_mtu; + /* Interface MTU */ + u16 xmit_dest_mac[ETH_ALEN / 2]; + /* Destination MAC address to use when forwarding */ + u16 xmit_src_mac[ETH_ALEN / 2]; + /* Source MAC address to use when forwarding */ + + /* + * Summary stats. + */ + u64 rx_packet_count64; + u64 rx_byte_count64; +}; + +/* + * Per-connection data structure. + */ +struct sfe_ipv4_connection { + struct sfe_ipv4_connection *next; + /* Pointer to the next entry in a hash chain */ + struct sfe_ipv4_connection *prev; + /* Pointer to the previous entry in a hash chain */ + int protocol; /* IP protocol number */ + __be32 src_ip; /* Src IP addr pre-translation */ + __be32 src_ip_xlate; /* Src IP addr post-translation */ + __be32 dest_ip; /* Dest IP addr pre-translation */ + __be32 dest_ip_xlate; /* Dest IP addr post-translation */ + __be16 src_port; /* Src port pre-translation */ + __be16 src_port_xlate; /* Src port post-translation */ + __be16 dest_port; /* Dest port pre-translation */ + __be16 dest_port_xlate; /* Dest port post-translation */ + struct sfe_ipv4_connection_match *original_match; + /* Original direction matching structure */ + struct net_device *original_dev; + /* Original direction source device */ + struct sfe_ipv4_connection_match *reply_match; + /* Reply direction matching structure */ + struct net_device *reply_dev; /* Reply direction source device */ + u64 last_sync_jiffies; /* Jiffies count for the last sync */ + struct sfe_ipv4_connection *all_connections_next; + /* Pointer to the next entry in the list of all connections */ + struct sfe_ipv4_connection *all_connections_prev; + /* Pointer to the previous entry in the list of all connections */ + u32 mark; /* mark for outgoing packet */ + u32 debug_read_seq; /* sequence number for debug dump */ +}; + +/* + * IPv4 connections and hash table size information. + */ +#define SFE_IPV4_CONNECTION_HASH_SHIFT 12 +#define SFE_IPV4_CONNECTION_HASH_SIZE (1 << SFE_IPV4_CONNECTION_HASH_SHIFT) +#define SFE_IPV4_CONNECTION_HASH_MASK (SFE_IPV4_CONNECTION_HASH_SIZE - 1) + +#ifdef CONFIG_NF_FLOW_COOKIE +#define SFE_FLOW_COOKIE_SIZE 2048 +#define SFE_FLOW_COOKIE_MASK 0x7ff + +struct sfe_flow_cookie_entry { + struct sfe_ipv4_connection_match *match; + unsigned long last_clean_time; +}; +#endif + +enum sfe_ipv4_exception_events { + SFE_IPV4_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_UDP_NO_CONNECTION, + SFE_IPV4_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT, + SFE_IPV4_EXCEPTION_EVENT_UDP_SMALL_TTL, + SFE_IPV4_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION, + SFE_IPV4_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS, + SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS, + SFE_IPV4_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT, + SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_TTL, + SFE_IPV4_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION, + SFE_IPV4_EXCEPTION_EVENT_TCP_FLAGS, + SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE, + SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS, + SFE_IPV4_EXCEPTION_EVENT_TCP_BAD_SACK, + SFE_IPV4_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS, + SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE, + SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE, + SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_NON_V4, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_IP_OPTIONS_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UDP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_TCP_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UNHANDLED_PROTOCOL, + SFE_IPV4_EXCEPTION_EVENT_ICMP_NO_CONNECTION, + SFE_IPV4_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION, + SFE_IPV4_EXCEPTION_EVENT_HEADER_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_BAD_TOTAL_LENGTH, + SFE_IPV4_EXCEPTION_EVENT_NON_V4, + SFE_IPV4_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT, + SFE_IPV4_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE, + SFE_IPV4_EXCEPTION_EVENT_UNHANDLED_PROTOCOL, + SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR, + SFE_IPV4_EXCEPTION_EVENT_LAST +}; + +static char *sfe_ipv4_exception_events_string[SFE_IPV4_EXCEPTION_EVENT_LAST] = { + "UDP_HEADER_INCOMPLETE", + "UDP_NO_CONNECTION", + "UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT", + "UDP_SMALL_TTL", + "UDP_NEEDS_FRAGMENTATION", + "TCP_HEADER_INCOMPLETE", + "TCP_NO_CONNECTION_SLOW_FLAGS", + "TCP_NO_CONNECTION_FAST_FLAGS", + "TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT", + "TCP_SMALL_TTL", + "TCP_NEEDS_FRAGMENTATION", + "TCP_FLAGS", + "TCP_SEQ_EXCEEDS_RIGHT_EDGE", + "TCP_SMALL_DATA_OFFS", + "TCP_BAD_SACK", + "TCP_BIG_DATA_OFFS", + "TCP_SEQ_BEFORE_LEFT_EDGE", + "TCP_ACK_EXCEEDS_RIGHT_EDGE", + "TCP_ACK_BEFORE_LEFT_EDGE", + "ICMP_HEADER_INCOMPLETE", + "ICMP_UNHANDLED_TYPE", + "ICMP_IPV4_HEADER_INCOMPLETE", + "ICMP_IPV4_NON_V4", + "ICMP_IPV4_IP_OPTIONS_INCOMPLETE", + "ICMP_IPV4_UDP_HEADER_INCOMPLETE", + "ICMP_IPV4_TCP_HEADER_INCOMPLETE", + "ICMP_IPV4_UNHANDLED_PROTOCOL", + "ICMP_NO_CONNECTION", + "ICMP_FLUSHED_CONNECTION", + "HEADER_INCOMPLETE", + "BAD_TOTAL_LENGTH", + "NON_V4", + "NON_INITIAL_FRAGMENT", + "DATAGRAM_INCOMPLETE", + "IP_OPTIONS_INCOMPLETE", + "UNHANDLED_PROTOCOL", + "CLONED_SKB_UNSHARE_ERROR" +}; + +/* + * Per-module structure. + */ +struct sfe_ipv4 { + spinlock_t lock; /* Lock for SMP correctness */ + struct sfe_ipv4_connection_match *active_head; + /* Head of the list of recently active connections */ + struct sfe_ipv4_connection_match *active_tail; + /* Tail of the list of recently active connections */ + struct sfe_ipv4_connection *all_connections_head; + /* Head of the list of all connections */ + struct sfe_ipv4_connection *all_connections_tail; + /* Tail of the list of all connections */ + unsigned int num_connections; /* Number of connections */ + struct timer_list timer; /* Timer used for periodic sync ops */ + sfe_sync_rule_callback_t __rcu sync_rule_callback; + /* Callback function registered by a connection manager for stats syncing */ + struct sfe_ipv4_connection *conn_hash[SFE_IPV4_CONNECTION_HASH_SIZE]; + /* Connection hash table */ + struct sfe_ipv4_connection_match *conn_match_hash[SFE_IPV4_CONNECTION_HASH_SIZE]; + /* Connection match hash table */ +#ifdef CONFIG_NF_FLOW_COOKIE + struct sfe_flow_cookie_entry sfe_flow_cookie_table[SFE_FLOW_COOKIE_SIZE]; + /* flow cookie table*/ + flow_cookie_set_func_t flow_cookie_set_func; + /* function used to configure flow cookie in hardware*/ + int flow_cookie_enable; + /* Enable/disable flow cookie at runtime */ +#endif + + /* + * Stats recorded in a sync period. These stats will be added to + * connection_xxx64 after a sync period. + */ + u32 connection_create_requests; + /* Number of IPv4 connection create requests */ + u32 connection_create_collisions; + /* Number of IPv4 connection create requests that collided with existing hash table entries */ + u32 connection_destroy_requests; + /* Number of IPv4 connection destroy requests */ + u32 connection_destroy_misses; + /* Number of IPv4 connection destroy requests that missed our hash table */ + u32 connection_match_hash_hits; + /* Number of IPv4 connection match hash hits */ + u32 connection_match_hash_reorders; + /* Number of IPv4 connection match hash reorders */ + u32 connection_flushes; /* Number of IPv4 connection flushes */ + u32 packets_forwarded; /* Number of IPv4 packets forwarded */ + u32 packets_not_forwarded; /* Number of IPv4 packets not forwarded */ + u32 exception_events[SFE_IPV4_EXCEPTION_EVENT_LAST]; + + /* + * Summary statistics. + */ + u64 connection_create_requests64; + /* Number of IPv4 connection create requests */ + u64 connection_create_collisions64; + /* Number of IPv4 connection create requests that collided with existing hash table entries */ + u64 connection_destroy_requests64; + /* Number of IPv4 connection destroy requests */ + u64 connection_destroy_misses64; + /* Number of IPv4 connection destroy requests that missed our hash table */ + u64 connection_match_hash_hits64; + /* Number of IPv4 connection match hash hits */ + u64 connection_match_hash_reorders64; + /* Number of IPv4 connection match hash reorders */ + u64 connection_flushes64; /* Number of IPv4 connection flushes */ + u64 packets_forwarded64; /* Number of IPv4 packets forwarded */ + u64 packets_not_forwarded64; + /* Number of IPv4 packets not forwarded */ + u64 exception_events64[SFE_IPV4_EXCEPTION_EVENT_LAST]; + + /* + * Control state. + */ + struct kobject *sys_sfe_ipv4; /* sysfs linkage */ + int debug_dev; /* Major number of the debug char device */ + u32 debug_read_seq; /* sequence number for debug dump */ +}; + +/* + * Enumeration of the XML output. + */ +enum sfe_ipv4_debug_xml_states { + SFE_IPV4_DEBUG_XML_STATE_START, + SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_START, + SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_CONNECTION, + SFE_IPV4_DEBUG_XML_STATE_CONNECTIONS_END, + SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_START, + SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_EXCEPTION, + SFE_IPV4_DEBUG_XML_STATE_EXCEPTIONS_END, + SFE_IPV4_DEBUG_XML_STATE_STATS, + SFE_IPV4_DEBUG_XML_STATE_END, + SFE_IPV4_DEBUG_XML_STATE_DONE +}; + +/* + * XML write state. + */ +struct sfe_ipv4_debug_xml_write_state { + enum sfe_ipv4_debug_xml_states state; + /* XML output file state machine state */ + int iter_exception; /* Next exception iterator */ +}; + +typedef bool (*sfe_ipv4_debug_xml_write_method_t)(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws); + +static struct sfe_ipv4 __si; + +/* + * sfe_ipv4_gen_ip_csum() + * Generate the IP checksum for an IPv4 header. + * + * Note that this function assumes that we have only 20 bytes of IP header. + */ +static inline u16 sfe_ipv4_gen_ip_csum(struct sfe_ipv4_ip_hdr *iph) +{ + u32 sum; + u16 *i = (u16 *)iph; + + iph->check = 0; + + /* + * Generate the sum. + */ + sum = i[0] + i[1] + i[2] + i[3] + i[4] + i[5] + i[6] + i[7] + i[8] + i[9]; + + /* + * Fold it to ones-complement form. + */ + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + + return (u16)sum ^ 0xffff; +} + +/* + * sfe_ipv4_get_connection_match_hash() + * Generate the hash used in connection match lookups. + */ +static inline unsigned int sfe_ipv4_get_connection_match_hash(struct net_device *dev, u8 protocol, + __be32 src_ip, __be16 src_port, + __be32 dest_ip, __be16 dest_port) +{ + size_t dev_addr = (size_t)dev; + u32 hash = ((u32)dev_addr) ^ ntohl(src_ip ^ dest_ip) ^ protocol ^ ntohs(src_port ^ dest_port); + return ((hash >> SFE_IPV4_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV4_CONNECTION_HASH_MASK; +} + +/* + * sfe_ipv4_find_sfe_ipv4_connection_match() + * Get the IPv4 flow match info that corresponds to a particular 5-tuple. + * + * On entry we must be holding the lock that protects the hash table. + */ +static struct sfe_ipv4_connection_match * +sfe_ipv4_find_sfe_ipv4_connection_match(struct sfe_ipv4 *si, struct net_device *dev, u8 protocol, + __be32 src_ip, __be16 src_port, + __be32 dest_ip, __be16 dest_port) +{ + struct sfe_ipv4_connection_match *cm; + struct sfe_ipv4_connection_match *head; + unsigned int conn_match_idx; + + conn_match_idx = sfe_ipv4_get_connection_match_hash(dev, protocol, src_ip, src_port, dest_ip, dest_port); + cm = si->conn_match_hash[conn_match_idx]; + + /* + * If we don't have anything in this chain then bail. + */ + if (unlikely(!cm)) { + return NULL; + } + + /* + * Hopefully the first entry is the one we want. + */ + if ((cm->match_src_port == src_port) + && (cm->match_dest_port == dest_port) + && (cm->match_src_ip == src_ip) + && (cm->match_dest_ip == dest_ip) + && (cm->match_protocol == protocol) + && (cm->match_dev == dev)) { + si->connection_match_hash_hits++; + return cm; + } + + /* + * Unfortunately we didn't find it at head, so we search it in chain and + * move matching entry to the top of the hash chain. We presume that this + * will be reused again very quickly. + */ + head = cm; + do { + cm = cm->next; + } while (cm && (cm->match_src_port != src_port + || cm->match_dest_port != dest_port + || cm->match_src_ip != src_ip + || cm->match_dest_ip != dest_ip + || cm->match_protocol != protocol + || cm->match_dev != dev)); + + /* + * Not found then we're done. + */ + if (unlikely(!cm)) { + return NULL; + } + + /* + * We found a match so move it. + */ + if (cm->next) { + cm->next->prev = cm->prev; + } + cm->prev->next = cm->next; + cm->prev = NULL; + cm->next = head; + head->prev = cm; + si->conn_match_hash[conn_match_idx] = cm; + si->connection_match_hash_reorders++; + + return cm; +} + +/* + * sfe_ipv4_connection_match_update_summary_stats() + * Update the summary stats for a connection match entry. + */ +static inline void sfe_ipv4_connection_match_update_summary_stats(struct sfe_ipv4_connection_match *cm) +{ + cm->rx_packet_count64 += cm->rx_packet_count; + cm->rx_packet_count = 0; + cm->rx_byte_count64 += cm->rx_byte_count; + cm->rx_byte_count = 0; +} + +/* + * sfe_ipv4_connection_match_compute_translations() + * Compute port and address translations for a connection match entry. + */ +static void sfe_ipv4_connection_match_compute_translations(struct sfe_ipv4_connection_match *cm) +{ + /* + * Before we insert the entry look to see if this is tagged as doing address + * translations. If it is then work out the adjustment that we need to apply + * to the transport checksum. + */ + if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC) { + /* + * Precompute an incremental checksum adjustment so we can + * edit packets in this stream very quickly. The algorithm is from RFC1624. + */ + u16 src_ip_hi = cm->match_src_ip >> 16; + u16 src_ip_lo = cm->match_src_ip & 0xffff; + u32 xlate_src_ip = ~cm->xlate_src_ip; + u16 xlate_src_ip_hi = xlate_src_ip >> 16; + u16 xlate_src_ip_lo = xlate_src_ip & 0xffff; + u16 xlate_src_port = ~cm->xlate_src_port; + u32 adj; + + /* + * When we compute this fold it down to a 16-bit offset + * as that way we can avoid having to do a double + * folding of the twos-complement result because the + * addition of 2 16-bit values cannot cause a double + * wrap-around! + */ + adj = src_ip_hi + src_ip_lo + cm->match_src_port + + xlate_src_ip_hi + xlate_src_ip_lo + xlate_src_port; + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_src_csum_adjustment = (u16)adj; + + } + + if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST) { + /* + * Precompute an incremental checksum adjustment so we can + * edit packets in this stream very quickly. The algorithm is from RFC1624. + */ + u16 dest_ip_hi = cm->match_dest_ip >> 16; + u16 dest_ip_lo = cm->match_dest_ip & 0xffff; + u32 xlate_dest_ip = ~cm->xlate_dest_ip; + u16 xlate_dest_ip_hi = xlate_dest_ip >> 16; + u16 xlate_dest_ip_lo = xlate_dest_ip & 0xffff; + u16 xlate_dest_port = ~cm->xlate_dest_port; + u32 adj; + + /* + * When we compute this fold it down to a 16-bit offset + * as that way we can avoid having to do a double + * folding of the twos-complement result because the + * addition of 2 16-bit values cannot cause a double + * wrap-around! + */ + adj = dest_ip_hi + dest_ip_lo + cm->match_dest_port + + xlate_dest_ip_hi + xlate_dest_ip_lo + xlate_dest_port; + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_dest_csum_adjustment = (u16)adj; + } + + if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC) { + u32 adj = ~cm->match_src_ip + cm->xlate_src_ip; + if (adj < cm->xlate_src_ip) { + adj++; + } + + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_src_partial_csum_adjustment = (u16)adj; + } + + if (cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST) { + u32 adj = ~cm->match_dest_ip + cm->xlate_dest_ip; + if (adj < cm->xlate_dest_ip) { + adj++; + } + + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_dest_partial_csum_adjustment = (u16)adj; + } + +} + +/* + * sfe_ipv4_update_summary_stats() + * Update the summary stats. + */ +static void sfe_ipv4_update_summary_stats(struct sfe_ipv4 *si) +{ + int i; + + si->connection_create_requests64 += si->connection_create_requests; + si->connection_create_requests = 0; + si->connection_create_collisions64 += si->connection_create_collisions; + si->connection_create_collisions = 0; + si->connection_destroy_requests64 += si->connection_destroy_requests; + si->connection_destroy_requests = 0; + si->connection_destroy_misses64 += si->connection_destroy_misses; + si->connection_destroy_misses = 0; + si->connection_match_hash_hits64 += si->connection_match_hash_hits; + si->connection_match_hash_hits = 0; + si->connection_match_hash_reorders64 += si->connection_match_hash_reorders; + si->connection_match_hash_reorders = 0; + si->connection_flushes64 += si->connection_flushes; + si->connection_flushes = 0; + si->packets_forwarded64 += si->packets_forwarded; + si->packets_forwarded = 0; + si->packets_not_forwarded64 += si->packets_not_forwarded; + si->packets_not_forwarded = 0; + + for (i = 0; i < SFE_IPV4_EXCEPTION_EVENT_LAST; i++) { + si->exception_events64[i] += si->exception_events[i]; + si->exception_events[i] = 0; + } +} + +/* + * sfe_ipv4_insert_sfe_ipv4_connection_match() + * Insert a connection match into the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline void sfe_ipv4_insert_sfe_ipv4_connection_match(struct sfe_ipv4 *si, + struct sfe_ipv4_connection_match *cm) +{ + struct sfe_ipv4_connection_match **hash_head; + struct sfe_ipv4_connection_match *prev_head; + unsigned int conn_match_idx + = sfe_ipv4_get_connection_match_hash(cm->match_dev, cm->match_protocol, + cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port); + + hash_head = &si->conn_match_hash[conn_match_idx]; + prev_head = *hash_head; + cm->prev = NULL; + if (prev_head) { + prev_head->prev = cm; + } + + cm->next = prev_head; + *hash_head = cm; + +#ifdef CONFIG_NF_FLOW_COOKIE + if (!si->flow_cookie_enable) + return; + + /* + * Configure hardware to put a flow cookie in packet of this flow, + * then we can accelerate the lookup process when we received this packet. + */ + for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { + struct sfe_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; + + if ((NULL == entry->match) && time_is_before_jiffies(entry->last_clean_time + HZ)) { + flow_cookie_set_func_t func; + + rcu_read_lock(); + func = rcu_dereference(si->flow_cookie_set_func); + if (func) { + if (!func(cm->match_protocol, cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port, conn_match_idx)) { + entry->match = cm; + cm->flow_cookie = conn_match_idx; + } + } + rcu_read_unlock(); + + break; + } + } +#endif +} + +/* + * sfe_ipv4_remove_sfe_ipv4_connection_match() + * Remove a connection match object from the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline void sfe_ipv4_remove_sfe_ipv4_connection_match(struct sfe_ipv4 *si, struct sfe_ipv4_connection_match *cm) +{ +#ifdef CONFIG_NF_FLOW_COOKIE + if (si->flow_cookie_enable) { + /* + * Tell hardware that we no longer need a flow cookie in packet of this flow + */ + unsigned int conn_match_idx; + + for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { + struct sfe_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; + + if (cm == entry->match) { + flow_cookie_set_func_t func; + + rcu_read_lock(); + func = rcu_dereference(si->flow_cookie_set_func); + if (func) { + func(cm->match_protocol, cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port, 0); + } + rcu_read_unlock(); + + cm->flow_cookie = 0; + entry->match = NULL; + entry->last_clean_time = jiffies; + break; + } + } + } +#endif + + /* + * Unlink the connection match entry from the hash. + */ + if (cm->prev) { + cm->prev->next = cm->next; + } else { + unsigned int conn_match_idx + = sfe_ipv4_get_connection_match_hash(cm->match_dev, cm->match_protocol, + cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port); + si->conn_match_hash[conn_match_idx] = cm->next; + } + + if (cm->next) { + cm->next->prev = cm->prev; + } + + /* + * If the connection match entry is in the active list remove it. + */ + if (cm->active) { + if (likely(cm->active_prev)) { + cm->active_prev->active_next = cm->active_next; + } else { + si->active_head = cm->active_next; + } + + if (likely(cm->active_next)) { + cm->active_next->active_prev = cm->active_prev; + } else { + si->active_tail = cm->active_prev; + } + } +} + +/* + * sfe_ipv4_get_connection_hash() + * Generate the hash used in connection lookups. + */ +static inline unsigned int sfe_ipv4_get_connection_hash(u8 protocol, __be32 src_ip, __be16 src_port, + __be32 dest_ip, __be16 dest_port) +{ + u32 hash = ntohl(src_ip ^ dest_ip) ^ protocol ^ ntohs(src_port ^ dest_port); + return ((hash >> SFE_IPV4_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV4_CONNECTION_HASH_MASK; +} + +/* + * sfe_ipv4_find_sfe_ipv4_connection() + * Get the IPv4 connection info that corresponds to a particular 5-tuple. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline struct sfe_ipv4_connection *sfe_ipv4_find_sfe_ipv4_connection(struct sfe_ipv4 *si, u32 protocol, + __be32 src_ip, __be16 src_port, + __be32 dest_ip, __be16 dest_port) +{ + struct sfe_ipv4_connection *c; + unsigned int conn_idx = sfe_ipv4_get_connection_hash(protocol, src_ip, src_port, dest_ip, dest_port); + c = si->conn_hash[conn_idx]; + + /* + * If we don't have anything in this chain then bale. + */ + if (unlikely(!c)) { + return NULL; + } + + /* + * Hopefully the first entry is the one we want. + */ + if ((c->src_port == src_port) + && (c->dest_port == dest_port) + && (c->src_ip == src_ip) + && (c->dest_ip == dest_ip) + && (c->protocol == protocol)) { + return c; + } + + /* + * Unfortunately we didn't find it at head, so we search it in chain. + */ + do { + c = c->next; + } while (c && (c->src_port != src_port + || c->dest_port != dest_port + || c->src_ip != src_ip + || c->dest_ip != dest_ip + || c->protocol != protocol)); + + /* + * Will need connection entry for next create/destroy metadata, + * So no need to re-order entry for these requests + */ + return c; +} + +/* + * sfe_ipv4_mark_rule() + * Updates the mark for a current offloaded connection + * + * Will take hash lock upon entry + */ +void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark) +{ + struct sfe_ipv4 *si = &__si; + struct sfe_ipv4_connection *c; + + spin_lock_bh(&si->lock); + c = sfe_ipv4_find_sfe_ipv4_connection(si, mark->protocol, + mark->src_ip.ip, mark->src_port, + mark->dest_ip.ip, mark->dest_port); + if (c) { + WARN_ON((0 != c->mark) && (0 == mark->mark)); + c->mark = mark->mark; + } + spin_unlock_bh(&si->lock); + + if (c) { + DEBUG_TRACE("Matching connection found for mark, " + "setting from %08x to %08x\n", + c->mark, mark->mark); + } +} + +/* + * sfe_ipv4_insert_sfe_ipv4_connection() + * Insert a connection into the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static void sfe_ipv4_insert_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c) +{ + struct sfe_ipv4_connection **hash_head; + struct sfe_ipv4_connection *prev_head; + unsigned int conn_idx; + + /* + * Insert entry into the connection hash. + */ + conn_idx = sfe_ipv4_get_connection_hash(c->protocol, c->src_ip, c->src_port, + c->dest_ip, c->dest_port); + hash_head = &si->conn_hash[conn_idx]; + prev_head = *hash_head; + c->prev = NULL; + if (prev_head) { + prev_head->prev = c; + } + + c->next = prev_head; + *hash_head = c; + + /* + * Insert entry into the "all connections" list. + */ + if (si->all_connections_tail) { + c->all_connections_prev = si->all_connections_tail; + si->all_connections_tail->all_connections_next = c; + } else { + c->all_connections_prev = NULL; + si->all_connections_head = c; + } + + si->all_connections_tail = c; + c->all_connections_next = NULL; + si->num_connections++; + + /* + * Insert the connection match objects too. + */ + sfe_ipv4_insert_sfe_ipv4_connection_match(si, c->original_match); + sfe_ipv4_insert_sfe_ipv4_connection_match(si, c->reply_match); +} + +/* + * sfe_ipv4_remove_sfe_ipv4_connection() + * Remove a sfe_ipv4_connection object from the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static void sfe_ipv4_remove_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c) +{ + /* + * Remove the connection match objects. + */ + sfe_ipv4_remove_sfe_ipv4_connection_match(si, c->reply_match); + sfe_ipv4_remove_sfe_ipv4_connection_match(si, c->original_match); + + /* + * Unlink the connection. + */ + if (c->prev) { + c->prev->next = c->next; + } else { + unsigned int conn_idx = sfe_ipv4_get_connection_hash(c->protocol, c->src_ip, c->src_port, + c->dest_ip, c->dest_port); + si->conn_hash[conn_idx] = c->next; + } + + if (c->next) { + c->next->prev = c->prev; + } + + /* + * Unlink connection from all_connections list + */ + if (c->all_connections_prev) { + c->all_connections_prev->all_connections_next = c->all_connections_next; + } else { + si->all_connections_head = c->all_connections_next; + } + + if (c->all_connections_next) { + c->all_connections_next->all_connections_prev = c->all_connections_prev; + } else { + si->all_connections_tail = c->all_connections_prev; + } + + si->num_connections--; +} + +/* + * sfe_ipv4_sync_sfe_ipv4_connection() + * Sync a connection. + * + * On entry to this function we expect that the lock for the connection is either + * already held or isn't required. + */ +static void sfe_ipv4_gen_sync_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_ipv4_connection *c, + struct sfe_connection_sync *sis, sfe_sync_reason_t reason, + u64 now_jiffies) +{ + struct sfe_ipv4_connection_match *original_cm; + struct sfe_ipv4_connection_match *reply_cm; + + /* + * Fill in the update message. + */ + sis->is_v6 = 0; + sis->protocol = c->protocol; + sis->src_ip.ip = c->src_ip; + sis->src_ip_xlate.ip = c->src_ip_xlate; + sis->dest_ip.ip = c->dest_ip; + sis->dest_ip_xlate.ip = c->dest_ip_xlate; + sis->src_port = c->src_port; + sis->src_port_xlate = c->src_port_xlate; + sis->dest_port = c->dest_port; + sis->dest_port_xlate = c->dest_port_xlate; + + original_cm = c->original_match; + reply_cm = c->reply_match; + sis->src_td_max_window = original_cm->protocol_state.tcp.max_win; + sis->src_td_end = original_cm->protocol_state.tcp.end; + sis->src_td_max_end = original_cm->protocol_state.tcp.max_end; + sis->dest_td_max_window = reply_cm->protocol_state.tcp.max_win; + sis->dest_td_end = reply_cm->protocol_state.tcp.end; + sis->dest_td_max_end = reply_cm->protocol_state.tcp.max_end; + + sis->src_new_packet_count = original_cm->rx_packet_count; + sis->src_new_byte_count = original_cm->rx_byte_count; + sis->dest_new_packet_count = reply_cm->rx_packet_count; + sis->dest_new_byte_count = reply_cm->rx_byte_count; + + sfe_ipv4_connection_match_update_summary_stats(original_cm); + sfe_ipv4_connection_match_update_summary_stats(reply_cm); + + sis->src_dev = original_cm->match_dev; + sis->src_packet_count = original_cm->rx_packet_count64; + sis->src_byte_count = original_cm->rx_byte_count64; + + sis->dest_dev = reply_cm->match_dev; + sis->dest_packet_count = reply_cm->rx_packet_count64; + sis->dest_byte_count = reply_cm->rx_byte_count64; + + sis->reason = reason; + + /* + * Get the time increment since our last sync. + */ + sis->delta_jiffies = now_jiffies - c->last_sync_jiffies; + c->last_sync_jiffies = now_jiffies; +} + +/* + * sfe_ipv4_flush_sfe_ipv4_connection() + * Flush a connection and free all associated resources. + * + * We need to be called with bottom halves disabled locally as we need to acquire + * the connection hash lock and release it again. In general we're actually called + * from within a BH and so we're fine, but we're also called when connections are + * torn down. + */ +static void sfe_ipv4_flush_sfe_ipv4_connection(struct sfe_ipv4 *si, + struct sfe_ipv4_connection *c, + sfe_sync_reason_t reason) +{ + struct sfe_connection_sync sis; + u64 now_jiffies; + sfe_sync_rule_callback_t sync_rule_callback; + + rcu_read_lock(); + spin_lock_bh(&si->lock); + si->connection_flushes++; + sync_rule_callback = rcu_dereference(si->sync_rule_callback); + spin_unlock_bh(&si->lock); + + if (sync_rule_callback) { + /* + * Generate a sync message and then sync. + */ + now_jiffies = get_jiffies_64(); + sfe_ipv4_gen_sync_sfe_ipv4_connection(si, c, &sis, reason, now_jiffies); + sync_rule_callback(&sis); + } + + rcu_read_unlock(); + + /* + * Release our hold of the source and dest devices and free the memory + * for our connection objects. + */ + dev_put(c->original_dev); + dev_put(c->reply_dev); + kfree(c->original_match); + kfree(c->reply_match); + kfree(c); +} + +/* + * sfe_ipv4_recv_udp() + * Handle UDP packet receives and forwarding. + */ +static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl, bool flush_on_find) +{ + struct sfe_ipv4_udp_hdr *udph; + __be32 src_ip; + __be32 dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv4_connection_match *cm; + u8 ttl; + struct net_device *xmit_dev; + + /* + * Is our packet too short to contain a valid UDP header? + */ + if (unlikely(!pskb_may_pull(skb, (sizeof(struct sfe_ipv4_udp_hdr) + ihl)))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for UDP header\n"); + return 0; + } + + /* + * Read the IP address and port information. Read the IP header data first + * because we've almost certainly got that in the cache. We may not yet have + * the UDP header cached though so allow more time for any prefetching. + */ + src_ip = iph->saddr; + dest_ip = iph->daddr; + + udph = (struct sfe_ipv4_udp_hdr *)(skb->data + ihl); + src_port = udph->source; + dest_port = udph->dest; + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. + */ +#ifdef CONFIG_NF_FLOW_COOKIE + cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; + if (unlikely(!cm)) { + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); + } +#else + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); +#endif + if (unlikely(!cm)) { + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_NO_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found\n"); + return 0; + } + + /* + * If our packet has beern marked as "flush on find" we can't actually + * forward it in the fast path, but now that we've found an associated + * connection we can flush that out before we process the packet. + */ + if (unlikely(flush_on_find)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("flush on find\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + +#ifdef CONFIG_XFRM + /* + * We can't accelerate the flow on this direction, just let it go + * through the slow path. + */ + if (unlikely(!cm->flow_accel)) { + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } +#endif + + /* + * Does our TTL allow forwarding? + */ + ttl = iph->ttl; + if (unlikely(ttl < 2)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_SMALL_TTL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ttl too low\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * If our packet is larger than the MTU of the transmit interface then + * we can't forward it easily. + */ + if (unlikely(len > cm->xmit_dev_mtu)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("larger than mtu\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * From this point on we're good to modify the packet. + */ + + /* + * Check if skb was cloned. If it was, unshare it. Because + * the data area is going to be written in this path and we don't want to + * change the cloned skb's data section. + */ + if (unlikely(skb_cloned(skb))) { + DEBUG_TRACE("%p: skb is a cloned skb\n", skb); + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + DEBUG_WARN("Failed to unshare the cloned skb\n"); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + return 0; + } + + /* + * Update the iph and udph pointers with the unshared skb's data area. + */ + iph = (struct sfe_ipv4_ip_hdr *)skb->data; + udph = (struct sfe_ipv4_udp_hdr *)(skb->data + ihl); + } + + /* + * Update DSCP + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { + iph->tos = (iph->tos & SFE_IPV4_DSCP_MASK) | cm->dscp; + } + + /* + * Decrement our TTL. + */ + iph->ttl = ttl - 1; + + /* + * Do we have to perform translations of the source address/port? + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) { + u16 udp_csum; + + iph->saddr = cm->xlate_src_ip; + udph->source = cm->xlate_src_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + udp_csum = udph->check; + if (likely(udp_csum)) { + u32 sum; + + if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { + sum = udp_csum + cm->xlate_src_partial_csum_adjustment; + } else { + sum = udp_csum + cm->xlate_src_csum_adjustment; + } + + sum = (sum & 0xffff) + (sum >> 16); + udph->check = (u16)sum; + } + } + + /* + * Do we have to perform translations of the destination address/port? + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST)) { + u16 udp_csum; + + iph->daddr = cm->xlate_dest_ip; + udph->dest = cm->xlate_dest_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + udp_csum = udph->check; + if (likely(udp_csum)) { + u32 sum; + + if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { + sum = udp_csum + cm->xlate_dest_partial_csum_adjustment; + } else { + sum = udp_csum + cm->xlate_dest_csum_adjustment; + } + + sum = (sum & 0xffff) + (sum >> 16); + udph->check = (u16)sum; + } + } + + /* + * Replace the IP checksum. + */ + iph->check = sfe_ipv4_gen_ip_csum(iph); + + /* + * Update traffic stats. + */ + cm->rx_packet_count++; + cm->rx_byte_count += len; + + /* + * If we're not already on the active list then insert ourselves at the tail + * of the current list. + */ + if (unlikely(!cm->active)) { + cm->active = true; + cm->active_prev = si->active_tail; + if (likely(si->active_tail)) { + si->active_tail->active_next = cm; + } else { + si->active_head = cm; + } + si->active_tail = cm; + } + + xmit_dev = cm->xmit_dev; + skb->dev = xmit_dev; + + /* + * Check to see if we need to write a header. + */ + if (likely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { + if (unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { + dev_hard_header(skb, xmit_dev, ETH_P_IP, + cm->xmit_dest_mac, cm->xmit_src_mac, len); + } else { + /* + * For the simple case we write this really fast. + */ + struct sfe_ipv4_eth_hdr *eth = (struct sfe_ipv4_eth_hdr *)__skb_push(skb, ETH_HLEN); + eth->h_proto = htons(ETH_P_IP); + eth->h_dest[0] = cm->xmit_dest_mac[0]; + eth->h_dest[1] = cm->xmit_dest_mac[1]; + eth->h_dest[2] = cm->xmit_dest_mac[2]; + eth->h_source[0] = cm->xmit_src_mac[0]; + eth->h_source[1] = cm->xmit_src_mac[1]; + eth->h_source[2] = cm->xmit_src_mac[2]; + } + } + + /* + * Update priority of skb. + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { + skb->priority = cm->priority; + } + + /* + * Mark outgoing packet. + */ + skb->mark = cm->connection->mark; + if (skb->mark) { + DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + } + + si->packets_forwarded++; + spin_unlock_bh(&si->lock); + + /* + * We're going to check for GSO flags when we transmit the packet so + * start fetching the necessary cache line now. + */ + prefetch(skb_shinfo(skb)); + + /* + * Mark that this packet has been fast forwarded. + */ + skb->fast_forwarded = 1; + + /* + * Send the packet on its way. + */ + dev_queue_xmit(skb); + + return 1; +} + +/* + * sfe_ipv4_process_tcp_option_sack() + * Parse TCP SACK option and update ack according + */ +static bool sfe_ipv4_process_tcp_option_sack(const struct sfe_ipv4_tcp_hdr *th, const u32 data_offs, + u32 *ack) +{ + u32 length = sizeof(struct sfe_ipv4_tcp_hdr); + u8 *ptr = (u8 *)th + length; + + /* + * Ignore processing if TCP packet has only TIMESTAMP option. + */ + if (likely(data_offs == length + TCPOLEN_TIMESTAMP + 1 + 1) + && likely(ptr[0] == TCPOPT_NOP) + && likely(ptr[1] == TCPOPT_NOP) + && likely(ptr[2] == TCPOPT_TIMESTAMP) + && likely(ptr[3] == TCPOLEN_TIMESTAMP)) { + return true; + } + + /* + * TCP options. Parse SACK option. + */ + while (length < data_offs) { + u8 size; + u8 kind; + + ptr = (u8 *)th + length; + kind = *ptr; + + /* + * NOP, for padding + * Not in the switch because to fast escape and to not calculate size + */ + if (kind == TCPOPT_NOP) { + length++; + continue; + } + + if (kind == TCPOPT_SACK) { + u32 sack = 0; + u8 re = 1 + 1; + + size = *(ptr + 1); + if ((size < (1 + 1 + TCPOLEN_SACK_PERBLOCK)) + || ((size - (1 + 1)) % (TCPOLEN_SACK_PERBLOCK)) + || (size > (data_offs - length))) { + return false; + } + + re += 4; + while (re < size) { + u32 sack_re; + u8 *sptr = ptr + re; + sack_re = (sptr[0] << 24) | (sptr[1] << 16) | (sptr[2] << 8) | sptr[3]; + if (sack_re > sack) { + sack = sack_re; + } + re += TCPOLEN_SACK_PERBLOCK; + } + if (sack > *ack) { + *ack = sack; + } + length += size; + continue; + } + if (kind == TCPOPT_EOL) { + return true; + } + size = *(ptr + 1); + if (size < 2) { + return false; + } + length += size; + } + + return true; +} + +/* + * sfe_ipv4_recv_tcp() + * Handle TCP packet receives and forwarding. + */ +static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl, bool flush_on_find) +{ + struct sfe_ipv4_tcp_hdr *tcph; + __be32 src_ip; + __be32 dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv4_connection_match *cm; + struct sfe_ipv4_connection_match *counter_cm; + u8 ttl; + u32 flags; + struct net_device *xmit_dev; + + /* + * Is our packet too short to contain a valid UDP header? + */ + if (unlikely(!pskb_may_pull(skb, (sizeof(struct sfe_ipv4_tcp_hdr) + ihl)))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for TCP header\n"); + return 0; + } + + /* + * Read the IP address and port information. Read the IP header data first + * because we've almost certainly got that in the cache. We may not yet have + * the TCP header cached though so allow more time for any prefetching. + */ + src_ip = iph->saddr; + dest_ip = iph->daddr; + + tcph = (struct sfe_ipv4_tcp_hdr *)(skb->data + ihl); + src_port = tcph->source; + dest_port = tcph->dest; + flags = tcp_flag_word(tcph); + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. + */ +#ifdef CONFIG_NF_FLOW_COOKIE + cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; + if (unlikely(!cm)) { + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); + } +#else + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); +#endif + if (unlikely(!cm)) { + /* + * We didn't get a connection but as TCP is connection-oriented that + * may be because this is a non-fast connection (not running established). + * For diagnostic purposes we differentiate this here. + */ + if (likely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) == TCP_FLAG_ACK)) { + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found - fast flags\n"); + return 0; + } + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found - slow flags: 0x%x\n", + flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); + return 0; + } + + /* + * If our packet has beern marked as "flush on find" we can't actually + * forward it in the fast path, but now that we've found an associated + * connection we can flush that out before we process the packet. + */ + if (unlikely(flush_on_find)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("flush on find\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + +#ifdef CONFIG_XFRM + /* + * We can't accelerate the flow on this direction, just let it go + * through the slow path. + */ + if (unlikely(!cm->flow_accel)) { + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } +#endif + /* + * Does our TTL allow forwarding? + */ + ttl = iph->ttl; + if (unlikely(ttl < 2)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_TTL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ttl too low\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * If our packet is larger than the MTU of the transmit interface then + * we can't forward it easily. + */ + if (unlikely((len > cm->xmit_dev_mtu) && !skb_is_gso(skb))) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("larger than mtu\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Look at our TCP flags. Anything missing an ACK or that has RST, SYN or FIN + * set is not a fast path packet. + */ + if (unlikely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) != TCP_FLAG_ACK)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP flags: 0x%x are not fast\n", + flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + counter_cm = cm->counter_match; + + /* + * Are we doing sequence number checking? + */ + if (likely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK))) { + u32 seq; + u32 ack; + u32 sack; + u32 data_offs; + u32 end; + u32 left_edge; + u32 scaled_win; + u32 max_end; + + /* + * Is our sequence fully past the right hand edge of the window? + */ + seq = ntohl(tcph->seq); + if (unlikely((s32)(seq - (cm->protocol_state.tcp.max_end + 1)) > 0)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("seq: %u exceeds right edge: %u\n", + seq, cm->protocol_state.tcp.max_end + 1); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Check that our TCP data offset isn't too short. + */ + data_offs = tcph->doff << 2; + if (unlikely(data_offs < sizeof(struct sfe_ipv4_tcp_hdr))) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP data offset: %u, too small\n", data_offs); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Update ACK according to any SACK option. + */ + ack = ntohl(tcph->ack_seq); + sack = ack; + if (unlikely(!sfe_ipv4_process_tcp_option_sack(tcph, data_offs, &sack))) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_BAD_SACK]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP option SACK size is wrong\n"); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Check that our TCP data offset isn't past the end of the packet. + */ + data_offs += sizeof(struct sfe_ipv4_ip_hdr); + if (unlikely(len < data_offs)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP data offset: %u, past end of packet: %u\n", + data_offs, len); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + end = seq + len - data_offs; + + /* + * Is our sequence fully before the left hand edge of the window? + */ + if (unlikely((s32)(end - (cm->protocol_state.tcp.end + - counter_cm->protocol_state.tcp.max_win - 1)) < 0)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("seq: %u before left edge: %u\n", + end, cm->protocol_state.tcp.end - counter_cm->protocol_state.tcp.max_win - 1); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Are we acking data that is to the right of what has been sent? + */ + if (unlikely((s32)(sack - (counter_cm->protocol_state.tcp.end + 1)) > 0)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ack: %u exceeds right edge: %u\n", + sack, counter_cm->protocol_state.tcp.end + 1); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Is our ack too far before the left hand edge of the window? + */ + left_edge = counter_cm->protocol_state.tcp.end + - cm->protocol_state.tcp.max_win + - SFE_IPV4_TCP_MAX_ACK_WINDOW + - 1; + if (unlikely((s32)(sack - left_edge) < 0)) { + struct sfe_ipv4_connection *c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ack: %u before left edge: %u\n", sack, left_edge); + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Have we just seen the largest window size yet for this connection? If yes + * then we need to record the new value. + */ + scaled_win = ntohs(tcph->window) << cm->protocol_state.tcp.win_scale; + scaled_win += (sack - ack); + if (unlikely(cm->protocol_state.tcp.max_win < scaled_win)) { + cm->protocol_state.tcp.max_win = scaled_win; + } + + /* + * If our sequence and/or ack numbers have advanced then record the new state. + */ + if (likely((s32)(end - cm->protocol_state.tcp.end) >= 0)) { + cm->protocol_state.tcp.end = end; + } + + max_end = sack + scaled_win; + if (likely((s32)(max_end - counter_cm->protocol_state.tcp.max_end) >= 0)) { + counter_cm->protocol_state.tcp.max_end = max_end; + } + } + + /* + * From this point on we're good to modify the packet. + */ + + /* + * Check if skb was cloned. If it was, unshare it. Because + * the data area is going to be written in this path and we don't want to + * change the cloned skb's data section. + */ + if (unlikely(skb_cloned(skb))) { + DEBUG_TRACE("%p: skb is a cloned skb\n", skb); + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + DEBUG_WARN("Failed to unshare the cloned skb\n"); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + return 0; + } + + /* + * Update the iph and tcph pointers with the unshared skb's data area. + */ + iph = (struct sfe_ipv4_ip_hdr *)skb->data; + tcph = (struct sfe_ipv4_tcp_hdr *)(skb->data + ihl); + } + + /* + * Update DSCP + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { + iph->tos = (iph->tos & SFE_IPV4_DSCP_MASK) | cm->dscp; + } + + /* + * Decrement our TTL. + */ + iph->ttl = ttl - 1; + + /* + * Do we have to perform translations of the source address/port? + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) { + u16 tcp_csum; + u32 sum; + + iph->saddr = cm->xlate_src_ip; + tcph->source = cm->xlate_src_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + tcp_csum = tcph->check; + if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { + sum = tcp_csum + cm->xlate_src_partial_csum_adjustment; + } else { + sum = tcp_csum + cm->xlate_src_csum_adjustment; + } + + sum = (sum & 0xffff) + (sum >> 16); + tcph->check = (u16)sum; + } + + /* + * Do we have to perform translations of the destination address/port? + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST)) { + u16 tcp_csum; + u32 sum; + + iph->daddr = cm->xlate_dest_ip; + tcph->dest = cm->xlate_dest_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + tcp_csum = tcph->check; + if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) { + sum = tcp_csum + cm->xlate_dest_partial_csum_adjustment; + } else { + sum = tcp_csum + cm->xlate_dest_csum_adjustment; + } + + sum = (sum & 0xffff) + (sum >> 16); + tcph->check = (u16)sum; + } + + /* + * Replace the IP checksum. + */ + iph->check = sfe_ipv4_gen_ip_csum(iph); + + /* + * Update traffic stats. + */ + cm->rx_packet_count++; + cm->rx_byte_count += len; + + /* + * If we're not already on the active list then insert ourselves at the tail + * of the current list. + */ + if (unlikely(!cm->active)) { + cm->active = true; + cm->active_prev = si->active_tail; + if (likely(si->active_tail)) { + si->active_tail->active_next = cm; + } else { + si->active_head = cm; + } + si->active_tail = cm; + } + + xmit_dev = cm->xmit_dev; + skb->dev = xmit_dev; + + /* + * Check to see if we need to write a header. + */ + if (likely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { + if (unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { + dev_hard_header(skb, xmit_dev, ETH_P_IP, + cm->xmit_dest_mac, cm->xmit_src_mac, len); + } else { + /* + * For the simple case we write this really fast. + */ + struct sfe_ipv4_eth_hdr *eth = (struct sfe_ipv4_eth_hdr *)__skb_push(skb, ETH_HLEN); + eth->h_proto = htons(ETH_P_IP); + eth->h_dest[0] = cm->xmit_dest_mac[0]; + eth->h_dest[1] = cm->xmit_dest_mac[1]; + eth->h_dest[2] = cm->xmit_dest_mac[2]; + eth->h_source[0] = cm->xmit_src_mac[0]; + eth->h_source[1] = cm->xmit_src_mac[1]; + eth->h_source[2] = cm->xmit_src_mac[2]; + } + } + + /* + * Update priority of skb. + */ + if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { + skb->priority = cm->priority; + } + + /* + * Mark outgoing packet + */ + skb->mark = cm->connection->mark; + if (skb->mark) { + DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + } + + si->packets_forwarded++; + spin_unlock_bh(&si->lock); + + /* + * We're going to check for GSO flags when we transmit the packet so + * start fetching the necessary cache line now. + */ + prefetch(skb_shinfo(skb)); + + /* + * Mark that this packet has been fast forwarded. + */ + skb->fast_forwarded = 1; + + /* + * Send the packet on its way. + */ + dev_queue_xmit(skb); + + return 1; +} + +/* + * sfe_ipv4_recv_icmp() + * Handle ICMP packet receives. + * + * ICMP packets aren't handled as a "fast path" and always have us process them + * through the default Linux stack. What we do need to do is look for any errors + * about connections we are handling in the fast path. If we find any such + * connections then we want to flush their state so that the ICMP error path + * within Linux has all of the correct state should it need it. + */ +static int sfe_ipv4_recv_icmp(struct sfe_ipv4 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv4_ip_hdr *iph, unsigned int ihl) +{ + struct icmphdr *icmph; + struct sfe_ipv4_ip_hdr *icmp_iph; + unsigned int icmp_ihl_words; + unsigned int icmp_ihl; + u32 *icmp_trans_h; + struct sfe_ipv4_udp_hdr *icmp_udph; + struct sfe_ipv4_tcp_hdr *icmp_tcph; + __be32 src_ip; + __be32 dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv4_connection_match *cm; + struct sfe_ipv4_connection *c; + u32 pull_len = sizeof(struct icmphdr) + ihl; + + /* + * Is our packet too short to contain a valid ICMP header? + */ + len -= ihl; + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for ICMP header\n"); + return 0; + } + + /* + * We only handle "destination unreachable" and "time exceeded" messages. + */ + icmph = (struct icmphdr *)(skb->data + ihl); + if ((icmph->type != ICMP_DEST_UNREACH) + && (icmph->type != ICMP_TIME_EXCEEDED)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("unhandled ICMP type: 0x%x\n", icmph->type); + return 0; + } + + /* + * Do we have the full embedded IP header? + */ + len -= sizeof(struct icmphdr); + pull_len += sizeof(struct sfe_ipv4_ip_hdr); + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Embedded IP header not complete\n"); + return 0; + } + + /* + * Is our embedded IP version wrong? + */ + icmp_iph = (struct sfe_ipv4_ip_hdr *)(icmph + 1); + if (unlikely(icmp_iph->version != 4)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_NON_V4]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("IP version: %u\n", icmp_iph->version); + return 0; + } + + /* + * Do we have the full embedded IP header, including any options? + */ + icmp_ihl_words = icmp_iph->ihl; + icmp_ihl = icmp_ihl_words << 2; + pull_len += icmp_ihl - sizeof(struct sfe_ipv4_ip_hdr); + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_IP_OPTIONS_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Embedded header not large enough for IP options\n"); + return 0; + } + + len -= icmp_ihl; + icmp_trans_h = ((u32 *)icmp_iph) + icmp_ihl_words; + + /* + * Handle the embedded transport layer header. + */ + switch (icmp_iph->protocol) { + case IPPROTO_UDP: + /* + * We should have 8 bytes of UDP header - that's enough to identify + * the connection. + */ + pull_len += 8; + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UDP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Incomplete embedded UDP header\n"); + return 0; + } + + icmp_udph = (struct sfe_ipv4_udp_hdr *)icmp_trans_h; + src_port = icmp_udph->source; + dest_port = icmp_udph->dest; + break; + + case IPPROTO_TCP: + /* + * We should have 8 bytes of TCP header - that's enough to identify + * the connection. + */ + pull_len += 8; + if (!pskb_may_pull(skb, pull_len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_TCP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Incomplete embedded TCP header\n"); + return 0; + } + + icmp_tcph = (struct sfe_ipv4_tcp_hdr *)icmp_trans_h; + src_port = icmp_tcph->source; + dest_port = icmp_tcph->dest; + break; + + default: + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Unhandled embedded IP protocol: %u\n", icmp_iph->protocol); + return 0; + } + + src_ip = icmp_iph->saddr; + dest_ip = icmp_iph->daddr; + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. Note that we reverse the source and destination + * here because our embedded message contains a packet that was sent in the + * opposite direction to the one in which we just received it. It will have + * been sent on the interface from which we received it though so that's still + * ok to use. + */ + cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, icmp_iph->protocol, dest_ip, dest_port, src_ip, src_port); + if (unlikely(!cm)) { + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_NO_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found\n"); + return 0; + } + + /* + * We found a connection so now remove it from the connection list and flush + * its state. + */ + c = cm->connection; + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; +} + +/* + * sfe_ipv4_recv() + * Handle packet receives and forwaring. + * + * Returns 1 if the packet is forwarded or 0 if it isn't. + */ +int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb) +{ + struct sfe_ipv4 *si = &__si; + unsigned int len; + unsigned int tot_len; + unsigned int frag_off; + unsigned int ihl; + bool flush_on_find; + bool ip_options; + struct sfe_ipv4_ip_hdr *iph; + u32 protocol; + + /* + * Check that we have space for an IP header here. + */ + len = skb->len; + if (unlikely(!pskb_may_pull(skb, sizeof(struct sfe_ipv4_ip_hdr)))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("len: %u is too short\n", len); + return 0; + } + + /* + * Check that our "total length" is large enough for an IP header. + */ + iph = (struct sfe_ipv4_ip_hdr *)skb->data; + tot_len = ntohs(iph->tot_len); + if (unlikely(tot_len < sizeof(struct sfe_ipv4_ip_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_BAD_TOTAL_LENGTH]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("tot_len: %u is too short\n", tot_len); + return 0; + } + + /* + * Is our IP version wrong? + */ + if (unlikely(iph->version != 4)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_NON_V4]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("IP version: %u\n", iph->version); + return 0; + } + + /* + * Does our datagram fit inside the skb? + */ + if (unlikely(tot_len > len)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("tot_len: %u, exceeds len: %u\n", tot_len, len); + return 0; + } + + /* + * Do we have a non-initial fragment? + */ + frag_off = ntohs(iph->frag_off); + if (unlikely(frag_off & IP_OFFSET)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("non-initial fragment\n"); + return 0; + } + + /* + * If we have a (first) fragment then mark it to cause any connection to flush. + */ + flush_on_find = unlikely(frag_off & IP_MF) ? true : false; + + /* + * Do we have any IP options? That's definite a slow path! If we do have IP + * options we need to recheck our header size. + */ + ihl = iph->ihl << 2; + ip_options = unlikely(ihl != sizeof(struct sfe_ipv4_ip_hdr)) ? true : false; + if (unlikely(ip_options)) { + if (unlikely(len < ihl)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("len: %u is too short for header of size: %u\n", len, ihl); + return 0; + } + + flush_on_find = true; + } + + protocol = iph->protocol; + if (IPPROTO_UDP == protocol) { + return sfe_ipv4_recv_udp(si, skb, dev, len, iph, ihl, flush_on_find); + } + + if (IPPROTO_TCP == protocol) { + return sfe_ipv4_recv_tcp(si, skb, dev, len, iph, ihl, flush_on_find); + } + + if (IPPROTO_ICMP == protocol) { + return sfe_ipv4_recv_icmp(si, skb, dev, len, iph, ihl); + } + + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("not UDP, TCP or ICMP: %u\n", protocol); + return 0; +} + +static void +sfe_ipv4_update_tcp_state(struct sfe_ipv4_connection *c, + struct sfe_connection_create *sic) +{ + struct sfe_ipv4_connection_match *orig_cm; + struct sfe_ipv4_connection_match *repl_cm; + struct sfe_ipv4_tcp_connection_match *orig_tcp; + struct sfe_ipv4_tcp_connection_match *repl_tcp; + + orig_cm = c->original_match; + repl_cm = c->reply_match; + orig_tcp = &orig_cm->protocol_state.tcp; + repl_tcp = &repl_cm->protocol_state.tcp; + + /* update orig */ + if (orig_tcp->max_win < sic->src_td_max_window) { + orig_tcp->max_win = sic->src_td_max_window; + } + if ((s32)(orig_tcp->end - sic->src_td_end) < 0) { + orig_tcp->end = sic->src_td_end; + } + if ((s32)(orig_tcp->max_end - sic->src_td_max_end) < 0) { + orig_tcp->max_end = sic->src_td_max_end; + } + + /* update reply */ + if (repl_tcp->max_win < sic->dest_td_max_window) { + repl_tcp->max_win = sic->dest_td_max_window; + } + if ((s32)(repl_tcp->end - sic->dest_td_end) < 0) { + repl_tcp->end = sic->dest_td_end; + } + if ((s32)(repl_tcp->max_end - sic->dest_td_max_end) < 0) { + repl_tcp->max_end = sic->dest_td_max_end; + } + + /* update match flags */ + orig_cm->flags &= ~SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + repl_cm->flags &= ~SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { + orig_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + repl_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + } +} + +static void +sfe_ipv4_update_protocol_state(struct sfe_ipv4_connection *c, + struct sfe_connection_create *sic) +{ + switch (sic->protocol) { + case IPPROTO_TCP: + sfe_ipv4_update_tcp_state(c, sic); + break; + } +} + +void sfe_ipv4_update_rule(struct sfe_connection_create *sic) +{ + struct sfe_ipv4_connection *c; + struct sfe_ipv4 *si = &__si; + + spin_lock_bh(&si->lock); + + c = sfe_ipv4_find_sfe_ipv4_connection(si, + sic->protocol, + sic->src_ip.ip, + sic->src_port, + sic->dest_ip.ip, + sic->dest_port); + if (c != NULL) { + sfe_ipv4_update_protocol_state(c, sic); + } + + spin_unlock_bh(&si->lock); +} + +/* + * sfe_ipv4_create_rule() + * Create a forwarding rule. + */ +int sfe_ipv4_create_rule(struct sfe_connection_create *sic) +{ + struct sfe_ipv4 *si = &__si; + struct sfe_ipv4_connection *c; + struct sfe_ipv4_connection_match *original_cm; + struct sfe_ipv4_connection_match *reply_cm; + struct net_device *dest_dev; + struct net_device *src_dev; + + dest_dev = sic->dest_dev; + src_dev = sic->src_dev; + + if (unlikely((dest_dev->reg_state != NETREG_REGISTERED) || + (src_dev->reg_state != NETREG_REGISTERED))) { + return -EINVAL; + } + + spin_lock_bh(&si->lock); + si->connection_create_requests++; + + /* + * Check to see if there is already a flow that matches the rule we're + * trying to create. If there is then we can't create a new one. + */ + c = sfe_ipv4_find_sfe_ipv4_connection(si, + sic->protocol, + sic->src_ip.ip, + sic->src_port, + sic->dest_ip.ip, + sic->dest_port); + if (c != NULL) { + si->connection_create_collisions++; + + /* + * If we already have the flow then it's likely that this + * request to create the connection rule contains more + * up-to-date information. Check and update accordingly. + */ + sfe_ipv4_update_protocol_state(c, sic); + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("connection already exists - mark: %08x, p: %d\n" + " s: %s:%pM:%pI4:%u, d: %s:%pM:%pI4:%u\n", + sic->mark, sic->protocol, + sic->src_dev->name, sic->src_mac, &sic->src_ip.ip, ntohs(sic->src_port), + sic->dest_dev->name, sic->dest_mac, &sic->dest_ip.ip, ntohs(sic->dest_port)); + return -EADDRINUSE; + } + + /* + * Allocate the various connection tracking objects. + */ + c = (struct sfe_ipv4_connection *)kmalloc(sizeof(struct sfe_ipv4_connection), GFP_ATOMIC); + if (unlikely(!c)) { + spin_unlock_bh(&si->lock); + return -ENOMEM; + } + + original_cm = (struct sfe_ipv4_connection_match *)kmalloc(sizeof(struct sfe_ipv4_connection_match), GFP_ATOMIC); + if (unlikely(!original_cm)) { + spin_unlock_bh(&si->lock); + kfree(c); + return -ENOMEM; + } + + reply_cm = (struct sfe_ipv4_connection_match *)kmalloc(sizeof(struct sfe_ipv4_connection_match), GFP_ATOMIC); + if (unlikely(!reply_cm)) { + spin_unlock_bh(&si->lock); + kfree(original_cm); + kfree(c); + return -ENOMEM; + } + + /* + * Fill in the "original" direction connection matching object. + * Note that the transmit MAC address is "dest_mac_xlate" because + * we always know both ends of a connection by their translated + * addresses and not their public addresses. + */ + original_cm->match_dev = src_dev; + original_cm->match_protocol = sic->protocol; + original_cm->match_src_ip = sic->src_ip.ip; + original_cm->match_src_port = sic->src_port; + original_cm->match_dest_ip = sic->dest_ip.ip; + original_cm->match_dest_port = sic->dest_port; + original_cm->xlate_src_ip = sic->src_ip_xlate.ip; + original_cm->xlate_src_port = sic->src_port_xlate; + original_cm->xlate_dest_ip = sic->dest_ip_xlate.ip; + original_cm->xlate_dest_port = sic->dest_port_xlate; + original_cm->rx_packet_count = 0; + original_cm->rx_packet_count64 = 0; + original_cm->rx_byte_count = 0; + original_cm->rx_byte_count64 = 0; + original_cm->xmit_dev = dest_dev; + original_cm->xmit_dev_mtu = sic->dest_mtu; + memcpy(original_cm->xmit_src_mac, dest_dev->dev_addr, ETH_ALEN); + memcpy(original_cm->xmit_dest_mac, sic->dest_mac_xlate, ETH_ALEN); + original_cm->connection = c; + original_cm->counter_match = reply_cm; + original_cm->flags = 0; + if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { + original_cm->priority = sic->src_priority; + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; + } + if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { + original_cm->dscp = sic->src_dscp << SFE_IPV4_DSCP_SHIFT; + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK; + } +#ifdef CONFIG_NF_FLOW_COOKIE + original_cm->flow_cookie = 0; +#endif +#ifdef CONFIG_XFRM + original_cm->flow_accel = sic->original_accel; +#endif + original_cm->active_next = NULL; + original_cm->active_prev = NULL; + original_cm->active = false; + + /* + * For PPP links we don't write an L2 header. For everything else we do. + */ + if (!(dest_dev->flags & IFF_POINTOPOINT)) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; + + /* + * If our dev writes Ethernet headers then we can write a really fast + * version. + */ + if (dest_dev->header_ops) { + if (dest_dev->header_ops->create == eth_header) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; + } + } + } + + /* + * Fill in the "reply" direction connection matching object. + */ + reply_cm->match_dev = dest_dev; + reply_cm->match_protocol = sic->protocol; + reply_cm->match_src_ip = sic->dest_ip_xlate.ip; + reply_cm->match_src_port = sic->dest_port_xlate; + reply_cm->match_dest_ip = sic->src_ip_xlate.ip; + reply_cm->match_dest_port = sic->src_port_xlate; + reply_cm->xlate_src_ip = sic->dest_ip.ip; + reply_cm->xlate_src_port = sic->dest_port; + reply_cm->xlate_dest_ip = sic->src_ip.ip; + reply_cm->xlate_dest_port = sic->src_port; + reply_cm->rx_packet_count = 0; + reply_cm->rx_packet_count64 = 0; + reply_cm->rx_byte_count = 0; + reply_cm->rx_byte_count64 = 0; + reply_cm->xmit_dev = src_dev; + reply_cm->xmit_dev_mtu = sic->src_mtu; + memcpy(reply_cm->xmit_src_mac, src_dev->dev_addr, ETH_ALEN); + memcpy(reply_cm->xmit_dest_mac, sic->src_mac, ETH_ALEN); + reply_cm->connection = c; + reply_cm->counter_match = original_cm; + reply_cm->flags = 0; + if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { + reply_cm->priority = sic->dest_priority; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; + } + if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { + reply_cm->dscp = sic->dest_dscp << SFE_IPV4_DSCP_SHIFT; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK; + } +#ifdef CONFIG_NF_FLOW_COOKIE + reply_cm->flow_cookie = 0; +#endif +#ifdef CONFIG_XFRM + reply_cm->flow_accel = sic->reply_accel; +#endif + reply_cm->active_next = NULL; + reply_cm->active_prev = NULL; + reply_cm->active = false; + + /* + * For PPP links we don't write an L2 header. For everything else we do. + */ + if (!(src_dev->flags & IFF_POINTOPOINT)) { + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; + + /* + * If our dev writes Ethernet headers then we can write a really fast + * version. + */ + if (src_dev->header_ops) { + if (src_dev->header_ops->create == eth_header) { + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; + } + } + } + + + if (sic->dest_ip.ip != sic->dest_ip_xlate.ip || sic->dest_port != sic->dest_port_xlate) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC; + } + + if (sic->src_ip.ip != sic->src_ip_xlate.ip || sic->src_port != sic->src_port_xlate) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST; + } + + c->protocol = sic->protocol; + c->src_ip = sic->src_ip.ip; + c->src_ip_xlate = sic->src_ip_xlate.ip; + c->src_port = sic->src_port; + c->src_port_xlate = sic->src_port_xlate; + c->original_dev = src_dev; + c->original_match = original_cm; + c->dest_ip = sic->dest_ip.ip; + c->dest_ip_xlate = sic->dest_ip_xlate.ip; + c->dest_port = sic->dest_port; + c->dest_port_xlate = sic->dest_port_xlate; + c->reply_dev = dest_dev; + c->reply_match = reply_cm; + c->mark = sic->mark; + c->debug_read_seq = 0; + c->last_sync_jiffies = get_jiffies_64(); + + /* + * Take hold of our source and dest devices for the duration of the connection. + */ + dev_hold(c->original_dev); + dev_hold(c->reply_dev); + + /* + * Initialize the protocol-specific information that we track. + */ + switch (sic->protocol) { + case IPPROTO_TCP: + original_cm->protocol_state.tcp.win_scale = sic->src_td_window_scale; + original_cm->protocol_state.tcp.max_win = sic->src_td_max_window ? sic->src_td_max_window : 1; + original_cm->protocol_state.tcp.end = sic->src_td_end; + original_cm->protocol_state.tcp.max_end = sic->src_td_max_end; + reply_cm->protocol_state.tcp.win_scale = sic->dest_td_window_scale; + reply_cm->protocol_state.tcp.max_win = sic->dest_td_max_window ? sic->dest_td_max_window : 1; + reply_cm->protocol_state.tcp.end = sic->dest_td_end; + reply_cm->protocol_state.tcp.max_end = sic->dest_td_max_end; + if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { + original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + } + break; + } + + sfe_ipv4_connection_match_compute_translations(original_cm); + sfe_ipv4_connection_match_compute_translations(reply_cm); + sfe_ipv4_insert_sfe_ipv4_connection(si, c); + + spin_unlock_bh(&si->lock); + + /* + * We have everything we need! + */ + DEBUG_INFO("new connection - mark: %08x, p: %d\n" + " s: %s:%pM(%pM):%pI4(%pI4):%u(%u)\n" + " d: %s:%pM(%pM):%pI4(%pI4):%u(%u)\n", + sic->mark, sic->protocol, + sic->src_dev->name, sic->src_mac, sic->src_mac_xlate, + &sic->src_ip.ip, &sic->src_ip_xlate.ip, ntohs(sic->src_port), ntohs(sic->src_port_xlate), + dest_dev->name, sic->dest_mac, sic->dest_mac_xlate, + &sic->dest_ip.ip, &sic->dest_ip_xlate.ip, ntohs(sic->dest_port), ntohs(sic->dest_port_xlate)); + + return 0; +} + +/* + * sfe_ipv4_destroy_rule() + * Destroy a forwarding rule. + */ +void sfe_ipv4_destroy_rule(struct sfe_connection_destroy *sid) +{ + struct sfe_ipv4 *si = &__si; + struct sfe_ipv4_connection *c; + + spin_lock_bh(&si->lock); + si->connection_destroy_requests++; + + /* + * Check to see if we have a flow that matches the rule we're trying + * to destroy. If there isn't then we can't destroy it. + */ + c = sfe_ipv4_find_sfe_ipv4_connection(si, sid->protocol, sid->src_ip.ip, sid->src_port, + sid->dest_ip.ip, sid->dest_port); + if (!c) { + si->connection_destroy_misses++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("connection does not exist - p: %d, s: %pI4:%u, d: %pI4:%u\n", + sid->protocol, &sid->src_ip, ntohs(sid->src_port), + &sid->dest_ip, ntohs(sid->dest_port)); + return; + } + + /* + * Remove our connection details from the hash tables. + */ + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + spin_unlock_bh(&si->lock); + + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_DESTROY); + + DEBUG_INFO("connection destroyed - p: %d, s: %pI4:%u, d: %pI4:%u\n", + sid->protocol, &sid->src_ip.ip, ntohs(sid->src_port), + &sid->dest_ip.ip, ntohs(sid->dest_port)); +} + +/* + * sfe_ipv4_register_sync_rule_callback() + * Register a callback for rule synchronization. + */ +void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t sync_rule_callback) +{ + struct sfe_ipv4 *si = &__si; + + spin_lock_bh(&si->lock); + rcu_assign_pointer(si->sync_rule_callback, sync_rule_callback); + spin_unlock_bh(&si->lock); +} + +/* + * sfe_ipv4_get_debug_dev() + */ +static ssize_t sfe_ipv4_get_debug_dev(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sfe_ipv4 *si = &__si; + ssize_t count; + int num; + + spin_lock_bh(&si->lock); + num = si->debug_dev; + spin_unlock_bh(&si->lock); + + count = snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", num); + return count; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_ipv4_debug_dev_attr = + __ATTR(debug_dev, S_IWUSR | S_IRUGO, sfe_ipv4_get_debug_dev, NULL); + +/* + * sfe_ipv4_destroy_all_rules_for_dev() + * Destroy all connections that match a particular device. + * + * If we pass dev as NULL then this destroys all connections. + */ +void sfe_ipv4_destroy_all_rules_for_dev(struct net_device *dev) +{ + struct sfe_ipv4 *si = &__si; + struct sfe_ipv4_connection *c; + +another_round: + spin_lock_bh(&si->lock); + + for (c = si->all_connections_head; c; c = c->all_connections_next) { + /* + * Does this connection relate to the device we are destroying? + */ + if (!dev + || (dev == c->original_dev) + || (dev == c->reply_dev)) { + break; + } + } + + if (c) { + sfe_ipv4_remove_sfe_ipv4_connection(si, c); + } + + spin_unlock_bh(&si->lock); + + if (c) { + sfe_ipv4_flush_sfe_ipv4_connection(si, c, SFE_SYNC_REASON_DESTROY); + goto another_round; + } +} + +/* + * sfe_ipv4_periodic_sync() + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +static void sfe_ipv4_periodic_sync(struct timer_list *arg) +#else +static void sfe_ipv4_periodic_sync(unsigned long arg) +#endif /*KERNEL_VERSION(4, 15, 0)*/ +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + struct sfe_ipv4 *si = (struct sfe_ipv4 *)arg->cust_data; +#else + struct sfe_ipv4 *si = (struct sfe_ipv4 *)arg; +#endif /*KERNEL_VERSION(4, 15, 0)*/ + u64 now_jiffies; + int quota; + sfe_sync_rule_callback_t sync_rule_callback; + + now_jiffies = get_jiffies_64(); + + rcu_read_lock(); + sync_rule_callback = rcu_dereference(si->sync_rule_callback); + if (!sync_rule_callback) { + rcu_read_unlock(); + goto done; + } + + spin_lock_bh(&si->lock); + sfe_ipv4_update_summary_stats(si); + + /* + * Get an estimate of the number of connections to parse in this sync. + */ + quota = (si->num_connections + 63) / 64; + + /* + * Walk the "active" list and sync the connection state. + */ + while (quota--) { + struct sfe_ipv4_connection_match *cm; + struct sfe_ipv4_connection_match *counter_cm; + struct sfe_ipv4_connection *c; + struct sfe_connection_sync sis; + + cm = si->active_head; + if (!cm) { + break; + } + + /* + * There's a possibility that our counter match is in the active list too. + * If it is then remove it. + */ + counter_cm = cm->counter_match; + if (counter_cm->active) { + counter_cm->active = false; + + /* + * We must have a connection preceding this counter match + * because that's the one that got us to this point, so we don't have + * to worry about removing the head of the list. + */ + counter_cm->active_prev->active_next = counter_cm->active_next; + + if (likely(counter_cm->active_next)) { + counter_cm->active_next->active_prev = counter_cm->active_prev; + } else { + si->active_tail = counter_cm->active_prev; + } + + counter_cm->active_next = NULL; + counter_cm->active_prev = NULL; + } + + /* + * Now remove the head of the active scan list. + */ + cm->active = false; + si->active_head = cm->active_next; + if (likely(cm->active_next)) { + cm->active_next->active_prev = NULL; + } else { + si->active_tail = NULL; + } + cm->active_next = NULL; + + /* + * Sync the connection state. + */ + c = cm->connection; + sfe_ipv4_gen_sync_sfe_ipv4_connection(si, c, &sis, SFE_SYNC_REASON_STATS, now_jiffies); + + /* + * We don't want to be holding the lock when we sync! + */ + spin_unlock_bh(&si->lock); + sync_rule_callback(&sis); + spin_lock_bh(&si->lock); + } + + spin_unlock_bh(&si->lock); + rcu_read_unlock(); + +done: + mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); +} + +#define CHAR_DEV_MSG_SIZE 768 + +/* + * sfe_ipv4_debug_dev_read_start() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + si->debug_read_seq++; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_connections_start() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_connections_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_connections_connection() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_connections_connection(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + struct sfe_ipv4_connection *c; + struct sfe_ipv4_connection_match *original_cm; + struct sfe_ipv4_connection_match *reply_cm; + int bytes_read; + int protocol; + struct net_device *src_dev; + __be32 src_ip; + __be32 src_ip_xlate; + __be16 src_port; + __be16 src_port_xlate; + u64 src_rx_packets; + u64 src_rx_bytes; + struct net_device *dest_dev; + __be32 dest_ip; + __be32 dest_ip_xlate; + __be16 dest_port; + __be16 dest_port_xlate; + u64 dest_rx_packets; + u64 dest_rx_bytes; + u64 last_sync_jiffies; + u32 mark, src_priority, dest_priority, src_dscp, dest_dscp; +#ifdef CONFIG_NF_FLOW_COOKIE + int src_flow_cookie, dst_flow_cookie; +#endif + + spin_lock_bh(&si->lock); + + for (c = si->all_connections_head; c; c = c->all_connections_next) { + if (c->debug_read_seq < si->debug_read_seq) { + c->debug_read_seq = si->debug_read_seq; + break; + } + } + + /* + * If there were no connections then move to the next state. + */ + if (!c) { + spin_unlock_bh(&si->lock); + ws->state++; + return true; + } + + original_cm = c->original_match; + reply_cm = c->reply_match; + + protocol = c->protocol; + src_dev = c->original_dev; + src_ip = c->src_ip; + src_ip_xlate = c->src_ip_xlate; + src_port = c->src_port; + src_port_xlate = c->src_port_xlate; + src_priority = original_cm->priority; + src_dscp = original_cm->dscp >> SFE_IPV4_DSCP_SHIFT; + + sfe_ipv4_connection_match_update_summary_stats(original_cm); + sfe_ipv4_connection_match_update_summary_stats(reply_cm); + + src_rx_packets = original_cm->rx_packet_count64; + src_rx_bytes = original_cm->rx_byte_count64; + dest_dev = c->reply_dev; + dest_ip = c->dest_ip; + dest_ip_xlate = c->dest_ip_xlate; + dest_port = c->dest_port; + dest_port_xlate = c->dest_port_xlate; + dest_priority = reply_cm->priority; + dest_dscp = reply_cm->dscp >> SFE_IPV4_DSCP_SHIFT; + dest_rx_packets = reply_cm->rx_packet_count64; + dest_rx_bytes = reply_cm->rx_byte_count64; + last_sync_jiffies = get_jiffies_64() - c->last_sync_jiffies; + mark = c->mark; +#ifdef CONFIG_NF_FLOW_COOKIE + src_flow_cookie = original_cm->flow_cookie; + dst_flow_cookie = reply_cm->flow_cookie; +#endif + spin_unlock_bh(&si->lock); + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\t\n", + protocol, + src_dev->name, + &src_ip, &src_ip_xlate, + ntohs(src_port), ntohs(src_port_xlate), + src_priority, src_dscp, + src_rx_packets, src_rx_bytes, + dest_dev->name, + &dest_ip, &dest_ip_xlate, + ntohs(dest_port), ntohs(dest_port_xlate), + dest_priority, dest_dscp, + dest_rx_packets, dest_rx_bytes, +#ifdef CONFIG_NF_FLOW_COOKIE + src_flow_cookie, dst_flow_cookie, +#endif + last_sync_jiffies, mark); + + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + return true; +} + +/* + * sfe_ipv4_debug_dev_read_connections_end() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_connections_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_exceptions_start() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_exceptions_start(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_exceptions_exception() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_exceptions_exception(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + u64 ct; + + spin_lock_bh(&si->lock); + ct = si->exception_events64[ws->iter_exception]; + spin_unlock_bh(&si->lock); + + if (ct) { + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, + "\t\t\n", + sfe_ipv4_exception_events_string[ws->iter_exception], + ct); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + } + + ws->iter_exception++; + if (ws->iter_exception >= SFE_IPV4_EXCEPTION_EVENT_LAST) { + ws->iter_exception = 0; + ws->state++; + } + + return true; +} + +/* + * sfe_ipv4_debug_dev_read_exceptions_end() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_exceptions_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_stats() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_stats(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + unsigned int num_connections; + u64 packets_forwarded; + u64 packets_not_forwarded; + u64 connection_create_requests; + u64 connection_create_collisions; + u64 connection_destroy_requests; + u64 connection_destroy_misses; + u64 connection_flushes; + u64 connection_match_hash_hits; + u64 connection_match_hash_reorders; + + spin_lock_bh(&si->lock); + sfe_ipv4_update_summary_stats(si); + + num_connections = si->num_connections; + packets_forwarded = si->packets_forwarded64; + packets_not_forwarded = si->packets_not_forwarded64; + connection_create_requests = si->connection_create_requests64; + connection_create_collisions = si->connection_create_collisions64; + connection_destroy_requests = si->connection_destroy_requests64; + connection_destroy_misses = si->connection_destroy_misses64; + connection_flushes = si->connection_flushes64; + connection_match_hash_hits = si->connection_match_hash_hits64; + connection_match_hash_reorders = si->connection_match_hash_reorders64; + spin_unlock_bh(&si->lock); + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n", + num_connections, + packets_forwarded, + packets_not_forwarded, + connection_create_requests, + connection_create_collisions, + connection_destroy_requests, + connection_destroy_misses, + connection_flushes, + connection_match_hash_hits, + connection_match_hash_reorders); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv4_debug_dev_read_end() + * Generate part of the XML output. + */ +static bool sfe_ipv4_debug_dev_read_end(struct sfe_ipv4 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv4_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * Array of write functions that write various XML elements that correspond to + * our XML output state machine. + */ +static sfe_ipv4_debug_xml_write_method_t sfe_ipv4_debug_xml_write_methods[SFE_IPV4_DEBUG_XML_STATE_DONE] = { + sfe_ipv4_debug_dev_read_start, + sfe_ipv4_debug_dev_read_connections_start, + sfe_ipv4_debug_dev_read_connections_connection, + sfe_ipv4_debug_dev_read_connections_end, + sfe_ipv4_debug_dev_read_exceptions_start, + sfe_ipv4_debug_dev_read_exceptions_exception, + sfe_ipv4_debug_dev_read_exceptions_end, + sfe_ipv4_debug_dev_read_stats, + sfe_ipv4_debug_dev_read_end, +}; + +/* + * sfe_ipv4_debug_dev_read() + * Send info to userspace upon read request from user + */ +static ssize_t sfe_ipv4_debug_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) +{ + char msg[CHAR_DEV_MSG_SIZE]; + int total_read = 0; + struct sfe_ipv4_debug_xml_write_state *ws; + struct sfe_ipv4 *si = &__si; + + ws = (struct sfe_ipv4_debug_xml_write_state *)filp->private_data; + while ((ws->state != SFE_IPV4_DEBUG_XML_STATE_DONE) && (length > CHAR_DEV_MSG_SIZE)) { + if ((sfe_ipv4_debug_xml_write_methods[ws->state])(si, buffer, msg, &length, &total_read, ws)) { + continue; + } + } + + return total_read; +} + +/* + * sfe_ipv4_debug_dev_write() + * Write to char device resets some stats + */ +static ssize_t sfe_ipv4_debug_dev_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) +{ + struct sfe_ipv4 *si = &__si; + + spin_lock_bh(&si->lock); + sfe_ipv4_update_summary_stats(si); + + si->packets_forwarded64 = 0; + si->packets_not_forwarded64 = 0; + si->connection_create_requests64 = 0; + si->connection_create_collisions64 = 0; + si->connection_destroy_requests64 = 0; + si->connection_destroy_misses64 = 0; + si->connection_flushes64 = 0; + si->connection_match_hash_hits64 = 0; + si->connection_match_hash_reorders64 = 0; + spin_unlock_bh(&si->lock); + + return length; +} + +/* + * sfe_ipv4_debug_dev_open() + */ +static int sfe_ipv4_debug_dev_open(struct inode *inode, struct file *file) +{ + struct sfe_ipv4_debug_xml_write_state *ws; + + ws = (struct sfe_ipv4_debug_xml_write_state *)file->private_data; + if (!ws) { + ws = kzalloc(sizeof(struct sfe_ipv4_debug_xml_write_state), GFP_KERNEL); + if (!ws) { + return -ENOMEM; + } + + ws->state = SFE_IPV4_DEBUG_XML_STATE_START; + file->private_data = ws; + } + + return 0; +} + +/* + * sfe_ipv4_debug_dev_release() + */ +static int sfe_ipv4_debug_dev_release(struct inode *inode, struct file *file) +{ + struct sfe_ipv4_debug_xml_write_state *ws; + + ws = (struct sfe_ipv4_debug_xml_write_state *)file->private_data; + if (ws) { + /* + * We've finished with our output so free the write state. + */ + kfree(ws); + } + + return 0; +} + +/* + * File operations used in the debug char device + */ +static struct file_operations sfe_ipv4_debug_dev_fops = { + .read = sfe_ipv4_debug_dev_read, + .write = sfe_ipv4_debug_dev_write, + .open = sfe_ipv4_debug_dev_open, + .release = sfe_ipv4_debug_dev_release +}; + +#ifdef CONFIG_NF_FLOW_COOKIE +/* + * sfe_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb) +{ + struct sfe_ipv4 *si = &__si; + + BUG_ON(!cb); + + if (si->flow_cookie_set_func) { + return -1; + } + + rcu_assign_pointer(si->flow_cookie_set_func, cb); + return 0; +} + +/* + * sfe_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb) +{ + struct sfe_ipv4 *si = &__si; + + RCU_INIT_POINTER(si->flow_cookie_set_func, NULL); + return 0; +} + +/* + * sfe_ipv4_get_flow_cookie() + */ +static ssize_t sfe_ipv4_get_flow_cookie(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sfe_ipv4 *si = &__si; + return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", si->flow_cookie_enable); +} + +/* + * sfe_ipv4_set_flow_cookie() + */ +static ssize_t sfe_ipv4_set_flow_cookie(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct sfe_ipv4 *si = &__si; + strict_strtol(buf, 0, (long int *)&si->flow_cookie_enable); + + return size; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_ipv4_flow_cookie_attr = + __ATTR(flow_cookie_enable, S_IWUSR | S_IRUGO, sfe_ipv4_get_flow_cookie, sfe_ipv4_set_flow_cookie); +#endif /*CONFIG_NF_FLOW_COOKIE*/ + +/* + * sfe_ipv4_init() + */ +static int __init sfe_ipv4_init(void) +{ + struct sfe_ipv4 *si = &__si; + int result = -1; + + DEBUG_INFO("SFE IPv4 init\n"); + + /* + * Create sys/sfe_ipv4 + */ + si->sys_sfe_ipv4 = kobject_create_and_add("sfe_ipv4", NULL); + if (!si->sys_sfe_ipv4) { + DEBUG_ERROR("failed to register sfe_ipv4\n"); + goto exit1; + } + + /* + * Create files, one for each parameter supported by this module. + */ + result = sysfs_create_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); + if (result) { + DEBUG_ERROR("failed to register debug dev file: %d\n", result); + goto exit2; + } + +#ifdef CONFIG_NF_FLOW_COOKIE + result = sysfs_create_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); + if (result) { + DEBUG_ERROR("failed to register flow cookie enable file: %d\n", result); + goto exit3; + } +#endif /* CONFIG_NF_FLOW_COOKIE */ + + /* + * Register our debug char device. + */ + result = register_chrdev(0, "sfe_ipv4", &sfe_ipv4_debug_dev_fops); + if (result < 0) { + DEBUG_ERROR("Failed to register chrdev: %d\n", result); + goto exit4; + } + + si->debug_dev = result; + + /* + * Create a timer to handle periodic statistics. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + timer_setup(&si->timer, sfe_ipv4_periodic_sync, 0); + si->timer.cust_data = (unsigned long)si; +#else + setup_timer(&si->timer, sfe_ipv4_periodic_sync, (unsigned long)si); +#endif /*KERNEL_VERSION(4, 15, 0)*/ + mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); + + spin_lock_init(&si->lock); + + return 0; + +exit4: +#ifdef CONFIG_NF_FLOW_COOKIE + sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); + +exit3: +#endif /* CONFIG_NF_FLOW_COOKIE */ + sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); + +exit2: + kobject_put(si->sys_sfe_ipv4); + +exit1: + return result; +} + +/* + * sfe_ipv4_exit() + */ +static void __exit sfe_ipv4_exit(void) +{ + struct sfe_ipv4 *si = &__si; + + DEBUG_INFO("SFE IPv4 exit\n"); + + /* + * Destroy all connections. + */ + sfe_ipv4_destroy_all_rules_for_dev(NULL); + + del_timer_sync(&si->timer); + + unregister_chrdev(si->debug_dev, "sfe_ipv4"); + +#ifdef CONFIG_NF_FLOW_COOKIE + sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr); +#endif /* CONFIG_NF_FLOW_COOKIE */ + sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr); + + kobject_put(si->sys_sfe_ipv4); + +} + +module_init(sfe_ipv4_init) +module_exit(sfe_ipv4_exit) + +EXPORT_SYMBOL(sfe_ipv4_recv); +EXPORT_SYMBOL(sfe_ipv4_create_rule); +EXPORT_SYMBOL(sfe_ipv4_destroy_rule); +EXPORT_SYMBOL(sfe_ipv4_destroy_all_rules_for_dev); +EXPORT_SYMBOL(sfe_ipv4_register_sync_rule_callback); +EXPORT_SYMBOL(sfe_ipv4_mark_rule); +EXPORT_SYMBOL(sfe_ipv4_update_rule); +#ifdef CONFIG_NF_FLOW_COOKIE +EXPORT_SYMBOL(sfe_register_flow_cookie_cb); +EXPORT_SYMBOL(sfe_unregister_flow_cookie_cb); +#endif + +MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv4 edition"); +MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/shortcut-fe/src/sfe_ipv6.c b/shortcut-fe/src/sfe_ipv6.c new file mode 100644 index 000000000..3c5ef1263 --- /dev/null +++ b/shortcut-fe/src/sfe_ipv6.c @@ -0,0 +1,3628 @@ +/* + * sfe_ipv6.c + * Shortcut forwarding engine - IPv6 support. + * + * Copyright (c) 2015-2016, 2019, The Linux Foundation. All rights reserved. + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sfe.h" +#include "sfe_cm.h" + +/* + * By default Linux IP header and transport layer header structures are + * unpacked, assuming that such headers should be 32-bit aligned. + * Unfortunately some wireless adaptors can't cope with this requirement and + * some CPUs can't handle misaligned accesses. For those platforms we + * define SFE_IPV6_UNALIGNED_IP_HEADER and mark the structures as packed. + * When we do this the compiler will generate slightly worse code than for the + * aligned case (on most platforms) but will be much quicker than fixing + * things up in an unaligned trap handler. + */ +#define SFE_IPV6_UNALIGNED_IP_HEADER 1 +#if SFE_IPV6_UNALIGNED_IP_HEADER +#define SFE_IPV6_UNALIGNED_STRUCT __attribute__((packed)) +#else +#define SFE_IPV6_UNALIGNED_STRUCT +#endif + +#define CHAR_DEV_MSG_SIZE 768 + +/* + * An Ethernet header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV6_UNALIGNED_STRUCT) + */ +struct sfe_ipv6_eth_hdr { + __be16 h_dest[ETH_ALEN / 2]; + __be16 h_source[ETH_ALEN / 2]; + __be16 h_proto; +} SFE_IPV6_UNALIGNED_STRUCT; + +#define SFE_IPV6_DSCP_MASK 0xf03f +#define SFE_IPV6_DSCP_SHIFT 2 + +/* + * An IPv6 header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV6_UNALIGNED_STRUCT) + */ +struct sfe_ipv6_ip_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 priority:4, + version:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 version:4, + priority:4; +#else +#error "Please fix " +#endif + __u8 flow_lbl[3]; + __be16 payload_len; + __u8 nexthdr; + __u8 hop_limit; + struct sfe_ipv6_addr saddr; + struct sfe_ipv6_addr daddr; + + /* + * The extension header start here. + */ +} SFE_IPV6_UNALIGNED_STRUCT; + +#define SFE_IPV6_EXT_HDR_HOP 0 +#define SFE_IPV6_EXT_HDR_ROUTING 43 +#define SFE_IPV6_EXT_HDR_FRAG 44 +#define SFE_IPV6_EXT_HDR_ESP 50 +#define SFE_IPV6_EXT_HDR_AH 51 +#define SFE_IPV6_EXT_HDR_NONE 59 +#define SFE_IPV6_EXT_HDR_DST 60 +#define SFE_IPV6_EXT_HDR_MH 135 + +/* + * fragmentation header + */ + +struct sfe_ipv6_frag_hdr { + __u8 nexthdr; + __u8 reserved; + __be16 frag_off; + __be32 identification; +}; + +#define SFE_IPV6_FRAG_OFFSET 0xfff8 + +/* + * generic IPv6 extension header + */ +struct sfe_ipv6_ext_hdr { + __u8 next_hdr; + __u8 hdr_len; + __u8 padding[6]; +} SFE_IPV6_UNALIGNED_STRUCT; + +/* + * A UDP header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV6_UNALIGNED_STRUCT) + */ +struct sfe_ipv6_udp_hdr { + __be16 source; + __be16 dest; + __be16 len; + __sum16 check; +} SFE_IPV6_UNALIGNED_STRUCT; + +/* + * A TCP header, but with an optional "packed" attribute to + * help with performance on some platforms (see the definition of + * SFE_IPV6_UNALIGNED_STRUCT) + */ +struct sfe_ipv6_tcp_hdr { + __be16 source; + __be16 dest; + __be32 seq; + __be32 ack_seq; +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 res1:4, + doff:4, + fin:1, + syn:1, + rst:1, + psh:1, + ack:1, + urg:1, + ece:1, + cwr:1; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u16 doff:4, + res1:4, + cwr:1, + ece:1, + urg:1, + ack:1, + psh:1, + rst:1, + syn:1, + fin:1; +#else +#error "Adjust your defines" +#endif + __be16 window; + __sum16 check; + __be16 urg_ptr; +} SFE_IPV6_UNALIGNED_STRUCT; + +/* + * Specifies the lower bound on ACK numbers carried in the TCP header + */ +#define SFE_IPV6_TCP_MAX_ACK_WINDOW 65520 + +/* + * IPv6 TCP connection match additional data. + */ +struct sfe_ipv6_tcp_connection_match { + u8 win_scale; /* Window scale */ + u32 max_win; /* Maximum window size seen */ + u32 end; /* Sequence number of the next byte to send (seq + segment length) */ + u32 max_end; /* Sequence number of the last byte to ack */ +}; + +/* + * Bit flags for IPv6 connection matching entry. + */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC (1<<0) + /* Perform source translation */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST (1<<1) + /* Perform destination translation */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK (1<<2) + /* Ignore TCP sequence numbers */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR (1<<3) + /* Fast Ethernet header write */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR (1<<4) + /* Fast Ethernet header write */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK (1<<5) + /* remark priority of SKB */ +#define SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK (1<<6) + /* remark DSCP of packet */ + +/* + * IPv6 connection matching structure. + */ +struct sfe_ipv6_connection_match { + /* + * References to other objects. + */ + struct sfe_ipv6_connection_match *next; + struct sfe_ipv6_connection_match *prev; + struct sfe_ipv6_connection *connection; + struct sfe_ipv6_connection_match *counter_match; + /* Matches the flow in the opposite direction as the one in connection */ + struct sfe_ipv6_connection_match *active_next; + struct sfe_ipv6_connection_match *active_prev; + bool active; /* Flag to indicate if we're on the active list */ + + /* + * Characteristics that identify flows that match this rule. + */ + struct net_device *match_dev; /* Network device */ + u8 match_protocol; /* Protocol */ + struct sfe_ipv6_addr match_src_ip[1]; /* Source IP address */ + struct sfe_ipv6_addr match_dest_ip[1]; /* Destination IP address */ + __be16 match_src_port; /* Source port/connection ident */ + __be16 match_dest_port; /* Destination port/connection ident */ + + /* + * Control the operations of the match. + */ + u32 flags; /* Bit flags */ +#ifdef CONFIG_NF_FLOW_COOKIE + u32 flow_cookie; /* used flow cookie, for debug */ +#endif +#ifdef CONFIG_XFRM + u32 flow_accel; /* The flow accelerated or not */ +#endif + + /* + * Connection state that we track once we match. + */ + union { /* Protocol-specific state */ + struct sfe_ipv6_tcp_connection_match tcp; + } protocol_state; + /* + * Stats recorded in a sync period. These stats will be added to + * rx_packet_count64/rx_byte_count64 after a sync period. + */ + u32 rx_packet_count; + u32 rx_byte_count; + + /* + * Packet translation information. + */ + struct sfe_ipv6_addr xlate_src_ip[1]; /* Address after source translation */ + __be16 xlate_src_port; /* Port/connection ident after source translation */ + u16 xlate_src_csum_adjustment; + /* Transport layer checksum adjustment after source translation */ + struct sfe_ipv6_addr xlate_dest_ip[1]; /* Address after destination translation */ + __be16 xlate_dest_port; /* Port/connection ident after destination translation */ + u16 xlate_dest_csum_adjustment; + /* Transport layer checksum adjustment after destination translation */ + + /* + * QoS information + */ + u32 priority; + u32 dscp; + + /* + * Packet transmit information. + */ + struct net_device *xmit_dev; /* Network device on which to transmit */ + unsigned short int xmit_dev_mtu; + /* Interface MTU */ + u16 xmit_dest_mac[ETH_ALEN / 2]; + /* Destination MAC address to use when forwarding */ + u16 xmit_src_mac[ETH_ALEN / 2]; + /* Source MAC address to use when forwarding */ + + /* + * Summary stats. + */ + u64 rx_packet_count64; + u64 rx_byte_count64; +}; + +/* + * Per-connection data structure. + */ +struct sfe_ipv6_connection { + struct sfe_ipv6_connection *next; + /* Pointer to the next entry in a hash chain */ + struct sfe_ipv6_connection *prev; + /* Pointer to the previous entry in a hash chain */ + int protocol; /* IP protocol number */ + struct sfe_ipv6_addr src_ip[1]; /* Src IP addr pre-translation */ + struct sfe_ipv6_addr src_ip_xlate[1]; /* Src IP addr post-translation */ + struct sfe_ipv6_addr dest_ip[1]; /* Dest IP addr pre-translation */ + struct sfe_ipv6_addr dest_ip_xlate[1]; /* Dest IP addr post-translation */ + __be16 src_port; /* Src port pre-translation */ + __be16 src_port_xlate; /* Src port post-translation */ + __be16 dest_port; /* Dest port pre-translation */ + __be16 dest_port_xlate; /* Dest port post-translation */ + struct sfe_ipv6_connection_match *original_match; + /* Original direction matching structure */ + struct net_device *original_dev; + /* Original direction source device */ + struct sfe_ipv6_connection_match *reply_match; + /* Reply direction matching structure */ + struct net_device *reply_dev; /* Reply direction source device */ + u64 last_sync_jiffies; /* Jiffies count for the last sync */ + struct sfe_ipv6_connection *all_connections_next; + /* Pointer to the next entry in the list of all connections */ + struct sfe_ipv6_connection *all_connections_prev; + /* Pointer to the previous entry in the list of all connections */ + u32 mark; /* mark for outgoing packet */ + u32 debug_read_seq; /* sequence number for debug dump */ +}; + +/* + * IPv6 connections and hash table size information. + */ +#define SFE_IPV6_CONNECTION_HASH_SHIFT 12 +#define SFE_IPV6_CONNECTION_HASH_SIZE (1 << SFE_IPV6_CONNECTION_HASH_SHIFT) +#define SFE_IPV6_CONNECTION_HASH_MASK (SFE_IPV6_CONNECTION_HASH_SIZE - 1) + +#ifdef CONFIG_NF_FLOW_COOKIE +#define SFE_FLOW_COOKIE_SIZE 2048 +#define SFE_FLOW_COOKIE_MASK 0x7ff + +struct sfe_ipv6_flow_cookie_entry { + struct sfe_ipv6_connection_match *match; + unsigned long last_clean_time; +}; +#endif + +enum sfe_ipv6_exception_events { + SFE_IPV6_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_UDP_NO_CONNECTION, + SFE_IPV6_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT, + SFE_IPV6_EXCEPTION_EVENT_UDP_SMALL_TTL, + SFE_IPV6_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION, + SFE_IPV6_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS, + SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS, + SFE_IPV6_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT, + SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_TTL, + SFE_IPV6_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION, + SFE_IPV6_EXCEPTION_EVENT_TCP_FLAGS, + SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE, + SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS, + SFE_IPV6_EXCEPTION_EVENT_TCP_BAD_SACK, + SFE_IPV6_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS, + SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE, + SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE, + SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_NON_V6, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_IP_OPTIONS_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UDP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_TCP_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UNHANDLED_PROTOCOL, + SFE_IPV6_EXCEPTION_EVENT_ICMP_NO_CONNECTION, + SFE_IPV6_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION, + SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_BAD_TOTAL_LENGTH, + SFE_IPV6_EXCEPTION_EVENT_NON_V6, + SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT, + SFE_IPV6_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE, + SFE_IPV6_EXCEPTION_EVENT_UNHANDLED_PROTOCOL, + SFE_IPV6_EXCEPTION_EVENT_FLOW_COOKIE_ADD_FAIL, + SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR, + SFE_IPV6_EXCEPTION_EVENT_LAST +}; + +static char *sfe_ipv6_exception_events_string[SFE_IPV6_EXCEPTION_EVENT_LAST] = { + "UDP_HEADER_INCOMPLETE", + "UDP_NO_CONNECTION", + "UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT", + "UDP_SMALL_TTL", + "UDP_NEEDS_FRAGMENTATION", + "TCP_HEADER_INCOMPLETE", + "TCP_NO_CONNECTION_SLOW_FLAGS", + "TCP_NO_CONNECTION_FAST_FLAGS", + "TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT", + "TCP_SMALL_TTL", + "TCP_NEEDS_FRAGMENTATION", + "TCP_FLAGS", + "TCP_SEQ_EXCEEDS_RIGHT_EDGE", + "TCP_SMALL_DATA_OFFS", + "TCP_BAD_SACK", + "TCP_BIG_DATA_OFFS", + "TCP_SEQ_BEFORE_LEFT_EDGE", + "TCP_ACK_EXCEEDS_RIGHT_EDGE", + "TCP_ACK_BEFORE_LEFT_EDGE", + "ICMP_HEADER_INCOMPLETE", + "ICMP_UNHANDLED_TYPE", + "ICMP_IPV6_HEADER_INCOMPLETE", + "ICMP_IPV6_NON_V6", + "ICMP_IPV6_IP_OPTIONS_INCOMPLETE", + "ICMP_IPV6_UDP_HEADER_INCOMPLETE", + "ICMP_IPV6_TCP_HEADER_INCOMPLETE", + "ICMP_IPV6_UNHANDLED_PROTOCOL", + "ICMP_NO_CONNECTION", + "ICMP_FLUSHED_CONNECTION", + "HEADER_INCOMPLETE", + "BAD_TOTAL_LENGTH", + "NON_V6", + "NON_INITIAL_FRAGMENT", + "DATAGRAM_INCOMPLETE", + "IP_OPTIONS_INCOMPLETE", + "UNHANDLED_PROTOCOL", + "FLOW_COOKIE_ADD_FAIL", + "CLONED_SKB_UNSHARE_ERROR" +}; + +/* + * Per-module structure. + */ +struct sfe_ipv6 { + spinlock_t lock; /* Lock for SMP correctness */ + struct sfe_ipv6_connection_match *active_head; + /* Head of the list of recently active connections */ + struct sfe_ipv6_connection_match *active_tail; + /* Tail of the list of recently active connections */ + struct sfe_ipv6_connection *all_connections_head; + /* Head of the list of all connections */ + struct sfe_ipv6_connection *all_connections_tail; + /* Tail of the list of all connections */ + unsigned int num_connections; /* Number of connections */ + struct timer_list timer; /* Timer used for periodic sync ops */ + sfe_sync_rule_callback_t __rcu sync_rule_callback; + /* Callback function registered by a connection manager for stats syncing */ + struct sfe_ipv6_connection *conn_hash[SFE_IPV6_CONNECTION_HASH_SIZE]; + /* Connection hash table */ + struct sfe_ipv6_connection_match *conn_match_hash[SFE_IPV6_CONNECTION_HASH_SIZE]; + /* Connection match hash table */ +#ifdef CONFIG_NF_FLOW_COOKIE + struct sfe_ipv6_flow_cookie_entry sfe_flow_cookie_table[SFE_FLOW_COOKIE_SIZE]; + /* flow cookie table*/ + sfe_ipv6_flow_cookie_set_func_t flow_cookie_set_func; + /* function used to configure flow cookie in hardware*/ + int flow_cookie_enable; + /* Enable/disable flow cookie at runtime */ +#endif + + /* + * Stats recorded in a sync period. These stats will be added to + * connection_xxx64 after a sync period. + */ + u32 connection_create_requests; + /* Number of IPv6 connection create requests */ + u32 connection_create_collisions; + /* Number of IPv6 connection create requests that collided with existing hash table entries */ + u32 connection_destroy_requests; + /* Number of IPv6 connection destroy requests */ + u32 connection_destroy_misses; + /* Number of IPv6 connection destroy requests that missed our hash table */ + u32 connection_match_hash_hits; + /* Number of IPv6 connection match hash hits */ + u32 connection_match_hash_reorders; + /* Number of IPv6 connection match hash reorders */ + u32 connection_flushes; /* Number of IPv6 connection flushes */ + u32 packets_forwarded; /* Number of IPv6 packets forwarded */ + u32 packets_not_forwarded; /* Number of IPv6 packets not forwarded */ + u32 exception_events[SFE_IPV6_EXCEPTION_EVENT_LAST]; + + /* + * Summary statistics. + */ + u64 connection_create_requests64; + /* Number of IPv6 connection create requests */ + u64 connection_create_collisions64; + /* Number of IPv6 connection create requests that collided with existing hash table entries */ + u64 connection_destroy_requests64; + /* Number of IPv6 connection destroy requests */ + u64 connection_destroy_misses64; + /* Number of IPv6 connection destroy requests that missed our hash table */ + u64 connection_match_hash_hits64; + /* Number of IPv6 connection match hash hits */ + u64 connection_match_hash_reorders64; + /* Number of IPv6 connection match hash reorders */ + u64 connection_flushes64; /* Number of IPv6 connection flushes */ + u64 packets_forwarded64; /* Number of IPv6 packets forwarded */ + u64 packets_not_forwarded64; + /* Number of IPv6 packets not forwarded */ + u64 exception_events64[SFE_IPV6_EXCEPTION_EVENT_LAST]; + + /* + * Control state. + */ + struct kobject *sys_sfe_ipv6; /* sysfs linkage */ + int debug_dev; /* Major number of the debug char device */ + u32 debug_read_seq; /* sequence number for debug dump */ +}; + +/* + * Enumeration of the XML output. + */ +enum sfe_ipv6_debug_xml_states { + SFE_IPV6_DEBUG_XML_STATE_START, + SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_START, + SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_CONNECTION, + SFE_IPV6_DEBUG_XML_STATE_CONNECTIONS_END, + SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_START, + SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_EXCEPTION, + SFE_IPV6_DEBUG_XML_STATE_EXCEPTIONS_END, + SFE_IPV6_DEBUG_XML_STATE_STATS, + SFE_IPV6_DEBUG_XML_STATE_END, + SFE_IPV6_DEBUG_XML_STATE_DONE +}; + +/* + * XML write state. + */ +struct sfe_ipv6_debug_xml_write_state { + enum sfe_ipv6_debug_xml_states state; + /* XML output file state machine state */ + int iter_exception; /* Next exception iterator */ +}; + +typedef bool (*sfe_ipv6_debug_xml_write_method_t)(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws); + +static struct sfe_ipv6 __si6; + +/* + * sfe_ipv6_get_debug_dev() + */ +static ssize_t sfe_ipv6_get_debug_dev(struct device *dev, struct device_attribute *attr, char *buf); + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_ipv6_debug_dev_attr = + __ATTR(debug_dev, S_IWUSR | S_IRUGO, sfe_ipv6_get_debug_dev, NULL); + +/* + * sfe_ipv6_is_ext_hdr() + * check if we recognize ipv6 extension header + */ +static inline bool sfe_ipv6_is_ext_hdr(u8 hdr) +{ + return (hdr == SFE_IPV6_EXT_HDR_HOP) || + (hdr == SFE_IPV6_EXT_HDR_ROUTING) || + (hdr == SFE_IPV6_EXT_HDR_FRAG) || + (hdr == SFE_IPV6_EXT_HDR_AH) || + (hdr == SFE_IPV6_EXT_HDR_DST) || + (hdr == SFE_IPV6_EXT_HDR_MH); +} + +/* + * sfe_ipv6_change_dsfield() + * change dscp field in IPv6 packet + */ +static inline void sfe_ipv6_change_dsfield(struct sfe_ipv6_ip_hdr *iph, u8 dscp) +{ + __be16 *p = (__be16 *)iph; + + *p = ((*p & htons(SFE_IPV6_DSCP_MASK)) | htons((u16)dscp << 4)); +} + +/* + * sfe_ipv6_get_connection_match_hash() + * Generate the hash used in connection match lookups. + */ +static inline unsigned int sfe_ipv6_get_connection_match_hash(struct net_device *dev, u8 protocol, + struct sfe_ipv6_addr *src_ip, __be16 src_port, + struct sfe_ipv6_addr *dest_ip, __be16 dest_port) +{ + u32 idx, hash = 0; + size_t dev_addr = (size_t)dev; + + for (idx = 0; idx < 4; idx++) { + hash ^= src_ip->addr[idx] ^ dest_ip->addr[idx]; + } + hash = ((u32)dev_addr) ^ hash ^ protocol ^ ntohs(src_port ^ dest_port); + return ((hash >> SFE_IPV6_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV6_CONNECTION_HASH_MASK; +} + +/* + * sfe_ipv6_find_connection_match() + * Get the IPv6 flow match info that corresponds to a particular 5-tuple. + * + * On entry we must be holding the lock that protects the hash table. + */ +static struct sfe_ipv6_connection_match * +sfe_ipv6_find_connection_match(struct sfe_ipv6 *si, struct net_device *dev, u8 protocol, + struct sfe_ipv6_addr *src_ip, __be16 src_port, + struct sfe_ipv6_addr *dest_ip, __be16 dest_port) +{ + struct sfe_ipv6_connection_match *cm; + struct sfe_ipv6_connection_match *head; + unsigned int conn_match_idx; + + conn_match_idx = sfe_ipv6_get_connection_match_hash(dev, protocol, src_ip, src_port, dest_ip, dest_port); + cm = si->conn_match_hash[conn_match_idx]; + + /* + * If we don't have anything in this chain then bail. + */ + if (unlikely(!cm)) { + return NULL; + } + + /* + * Hopefully the first entry is the one we want. + */ + if ((cm->match_src_port == src_port) + && (cm->match_dest_port == dest_port) + && (sfe_ipv6_addr_equal(cm->match_src_ip, src_ip)) + && (sfe_ipv6_addr_equal(cm->match_dest_ip, dest_ip)) + && (cm->match_protocol == protocol) + && (cm->match_dev == dev)) { + si->connection_match_hash_hits++; + return cm; + } + + /* + * Unfortunately we didn't find it at head, so we search it in chain and + * move matching entry to the top of the hash chain. We presume that this + * will be reused again very quickly. + */ + head = cm; + do { + cm = cm->next; + } while (cm && (cm->match_src_port != src_port + || cm->match_dest_port != dest_port + || !sfe_ipv6_addr_equal(cm->match_src_ip, src_ip) + || !sfe_ipv6_addr_equal(cm->match_dest_ip, dest_ip) + || cm->match_protocol != protocol + || cm->match_dev != dev)); + + /* + * Not found then we're done. + */ + if (unlikely(!cm)) { + return NULL; + } + + /* + * We found a match so move it. + */ + if (cm->next) { + cm->next->prev = cm->prev; + } + cm->prev->next = cm->next; + cm->prev = NULL; + cm->next = head; + head->prev = cm; + si->conn_match_hash[conn_match_idx] = cm; + si->connection_match_hash_reorders++; + + return cm; +} + +/* + * sfe_ipv6_connection_match_update_summary_stats() + * Update the summary stats for a connection match entry. + */ +static inline void sfe_ipv6_connection_match_update_summary_stats(struct sfe_ipv6_connection_match *cm) +{ + cm->rx_packet_count64 += cm->rx_packet_count; + cm->rx_packet_count = 0; + cm->rx_byte_count64 += cm->rx_byte_count; + cm->rx_byte_count = 0; +} + +/* + * sfe_ipv6_connection_match_compute_translations() + * Compute port and address translations for a connection match entry. + */ +static void sfe_ipv6_connection_match_compute_translations(struct sfe_ipv6_connection_match *cm) +{ + u32 diff[9]; + u32 *idx_32; + u16 *idx_16; + + /* + * Before we insert the entry look to see if this is tagged as doing address + * translations. If it is then work out the adjustment that we need to apply + * to the transport checksum. + */ + if (cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC) { + u32 adj = 0; + u32 carry = 0; + + /* + * Precompute an incremental checksum adjustment so we can + * edit packets in this stream very quickly. The algorithm is from RFC1624. + */ + idx_32 = diff; + *(idx_32++) = cm->match_src_ip->addr[0]; + *(idx_32++) = cm->match_src_ip->addr[1]; + *(idx_32++) = cm->match_src_ip->addr[2]; + *(idx_32++) = cm->match_src_ip->addr[3]; + + idx_16 = (u16 *)idx_32; + *(idx_16++) = cm->match_src_port; + *(idx_16++) = ~cm->xlate_src_port; + idx_32 = (u32 *)idx_16; + + *(idx_32++) = ~cm->xlate_src_ip->addr[0]; + *(idx_32++) = ~cm->xlate_src_ip->addr[1]; + *(idx_32++) = ~cm->xlate_src_ip->addr[2]; + *(idx_32++) = ~cm->xlate_src_ip->addr[3]; + + /* + * When we compute this fold it down to a 16-bit offset + * as that way we can avoid having to do a double + * folding of the twos-complement result because the + * addition of 2 16-bit values cannot cause a double + * wrap-around! + */ + for (idx_32 = diff; idx_32 < diff + 9; idx_32++) { + u32 w = *idx_32; + adj += carry; + adj += w; + carry = (w > adj); + } + adj += carry; + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_src_csum_adjustment = (u16)adj; + } + + if (cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST) { + u32 adj = 0; + u32 carry = 0; + + /* + * Precompute an incremental checksum adjustment so we can + * edit packets in this stream very quickly. The algorithm is from RFC1624. + */ + idx_32 = diff; + *(idx_32++) = cm->match_dest_ip->addr[0]; + *(idx_32++) = cm->match_dest_ip->addr[1]; + *(idx_32++) = cm->match_dest_ip->addr[2]; + *(idx_32++) = cm->match_dest_ip->addr[3]; + + idx_16 = (u16 *)idx_32; + *(idx_16++) = cm->match_dest_port; + *(idx_16++) = ~cm->xlate_dest_port; + idx_32 = (u32 *)idx_16; + + *(idx_32++) = ~cm->xlate_dest_ip->addr[0]; + *(idx_32++) = ~cm->xlate_dest_ip->addr[1]; + *(idx_32++) = ~cm->xlate_dest_ip->addr[2]; + *(idx_32++) = ~cm->xlate_dest_ip->addr[3]; + + /* + * When we compute this fold it down to a 16-bit offset + * as that way we can avoid having to do a double + * folding of the twos-complement result because the + * addition of 2 16-bit values cannot cause a double + * wrap-around! + */ + for (idx_32 = diff; idx_32 < diff + 9; idx_32++) { + u32 w = *idx_32; + adj += carry; + adj += w; + carry = (w > adj); + } + adj += carry; + adj = (adj & 0xffff) + (adj >> 16); + adj = (adj & 0xffff) + (adj >> 16); + cm->xlate_dest_csum_adjustment = (u16)adj; + } +} + +/* + * sfe_ipv6_update_summary_stats() + * Update the summary stats. + */ +static void sfe_ipv6_update_summary_stats(struct sfe_ipv6 *si) +{ + int i; + + si->connection_create_requests64 += si->connection_create_requests; + si->connection_create_requests = 0; + si->connection_create_collisions64 += si->connection_create_collisions; + si->connection_create_collisions = 0; + si->connection_destroy_requests64 += si->connection_destroy_requests; + si->connection_destroy_requests = 0; + si->connection_destroy_misses64 += si->connection_destroy_misses; + si->connection_destroy_misses = 0; + si->connection_match_hash_hits64 += si->connection_match_hash_hits; + si->connection_match_hash_hits = 0; + si->connection_match_hash_reorders64 += si->connection_match_hash_reorders; + si->connection_match_hash_reorders = 0; + si->connection_flushes64 += si->connection_flushes; + si->connection_flushes = 0; + si->packets_forwarded64 += si->packets_forwarded; + si->packets_forwarded = 0; + si->packets_not_forwarded64 += si->packets_not_forwarded; + si->packets_not_forwarded = 0; + + for (i = 0; i < SFE_IPV6_EXCEPTION_EVENT_LAST; i++) { + si->exception_events64[i] += si->exception_events[i]; + si->exception_events[i] = 0; + } +} + +/* + * sfe_ipv6_insert_connection_match() + * Insert a connection match into the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline void sfe_ipv6_insert_connection_match(struct sfe_ipv6 *si, + struct sfe_ipv6_connection_match *cm) +{ + struct sfe_ipv6_connection_match **hash_head; + struct sfe_ipv6_connection_match *prev_head; + unsigned int conn_match_idx + = sfe_ipv6_get_connection_match_hash(cm->match_dev, cm->match_protocol, + cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port); + + hash_head = &si->conn_match_hash[conn_match_idx]; + prev_head = *hash_head; + cm->prev = NULL; + if (prev_head) { + prev_head->prev = cm; + } + + cm->next = prev_head; + *hash_head = cm; + +#ifdef CONFIG_NF_FLOW_COOKIE + if (!si->flow_cookie_enable || !(cm->flags & (SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC | SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST))) + return; + + /* + * Configure hardware to put a flow cookie in packet of this flow, + * then we can accelerate the lookup process when we received this packet. + */ + for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { + struct sfe_ipv6_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; + + if ((NULL == entry->match) && time_is_before_jiffies(entry->last_clean_time + HZ)) { + sfe_ipv6_flow_cookie_set_func_t func; + + rcu_read_lock(); + func = rcu_dereference(si->flow_cookie_set_func); + if (func) { + if (!func(cm->match_protocol, cm->match_src_ip->addr, cm->match_src_port, + cm->match_dest_ip->addr, cm->match_dest_port, conn_match_idx)) { + entry->match = cm; + cm->flow_cookie = conn_match_idx; + } else { + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_FLOW_COOKIE_ADD_FAIL]++; + } + } + rcu_read_unlock(); + + break; + } + } +#endif +} + +/* + * sfe_ipv6_remove_connection_match() + * Remove a connection match object from the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline void sfe_ipv6_remove_connection_match(struct sfe_ipv6 *si, struct sfe_ipv6_connection_match *cm) +{ +#ifdef CONFIG_NF_FLOW_COOKIE + if (si->flow_cookie_enable) { + /* + * Tell hardware that we no longer need a flow cookie in packet of this flow + */ + unsigned int conn_match_idx; + + for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) { + struct sfe_ipv6_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx]; + + if (cm == entry->match) { + sfe_ipv6_flow_cookie_set_func_t func; + + rcu_read_lock(); + func = rcu_dereference(si->flow_cookie_set_func); + if (func) { + func(cm->match_protocol, cm->match_src_ip->addr, cm->match_src_port, + cm->match_dest_ip->addr, cm->match_dest_port, 0); + } + rcu_read_unlock(); + + cm->flow_cookie = 0; + entry->match = NULL; + entry->last_clean_time = jiffies; + break; + } + } + } +#endif + + /* + * Unlink the connection match entry from the hash. + */ + if (cm->prev) { + cm->prev->next = cm->next; + } else { + unsigned int conn_match_idx + = sfe_ipv6_get_connection_match_hash(cm->match_dev, cm->match_protocol, + cm->match_src_ip, cm->match_src_port, + cm->match_dest_ip, cm->match_dest_port); + si->conn_match_hash[conn_match_idx] = cm->next; + } + + if (cm->next) { + cm->next->prev = cm->prev; + } + + /* + * If the connection match entry is in the active list remove it. + */ + if (cm->active) { + if (likely(cm->active_prev)) { + cm->active_prev->active_next = cm->active_next; + } else { + si->active_head = cm->active_next; + } + + if (likely(cm->active_next)) { + cm->active_next->active_prev = cm->active_prev; + } else { + si->active_tail = cm->active_prev; + } + } +} + +/* + * sfe_ipv6_get_connection_hash() + * Generate the hash used in connection lookups. + */ +static inline unsigned int sfe_ipv6_get_connection_hash(u8 protocol, struct sfe_ipv6_addr *src_ip, __be16 src_port, + struct sfe_ipv6_addr *dest_ip, __be16 dest_port) +{ + u32 idx, hash = 0; + + for (idx = 0; idx < 4; idx++) { + hash ^= src_ip->addr[idx] ^ dest_ip->addr[idx]; + } + hash = hash ^ protocol ^ ntohs(src_port ^ dest_port); + return ((hash >> SFE_IPV6_CONNECTION_HASH_SHIFT) ^ hash) & SFE_IPV6_CONNECTION_HASH_MASK; +} + +/* + * sfe_ipv6_find_connection() + * Get the IPv6 connection info that corresponds to a particular 5-tuple. + * + * On entry we must be holding the lock that protects the hash table. + */ +static inline struct sfe_ipv6_connection *sfe_ipv6_find_connection(struct sfe_ipv6 *si, u32 protocol, + struct sfe_ipv6_addr *src_ip, __be16 src_port, + struct sfe_ipv6_addr *dest_ip, __be16 dest_port) +{ + struct sfe_ipv6_connection *c; + unsigned int conn_idx = sfe_ipv6_get_connection_hash(protocol, src_ip, src_port, dest_ip, dest_port); + c = si->conn_hash[conn_idx]; + + /* + * If we don't have anything in this chain then bale. + */ + if (unlikely(!c)) { + return NULL; + } + + /* + * Hopefully the first entry is the one we want. + */ + if ((c->src_port == src_port) + && (c->dest_port == dest_port) + && (sfe_ipv6_addr_equal(c->src_ip, src_ip)) + && (sfe_ipv6_addr_equal(c->dest_ip, dest_ip)) + && (c->protocol == protocol)) { + return c; + } + + /* + * Unfortunately we didn't find it at head, so we search it in chain. + */ + do { + c = c->next; + } while (c && (c->src_port != src_port + || c->dest_port != dest_port + || !sfe_ipv6_addr_equal(c->src_ip, src_ip) + || !sfe_ipv6_addr_equal(c->dest_ip, dest_ip) + || c->protocol != protocol)); + + /* + * Will need connection entry for next create/destroy metadata, + * So no need to re-order entry for these requests + */ + return c; +} + +/* + * sfe_ipv6_mark_rule() + * Updates the mark for a current offloaded connection + * + * Will take hash lock upon entry + */ +void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark) +{ + struct sfe_ipv6 *si = &__si6; + struct sfe_ipv6_connection *c; + + spin_lock_bh(&si->lock); + c = sfe_ipv6_find_connection(si, mark->protocol, + mark->src_ip.ip6, mark->src_port, + mark->dest_ip.ip6, mark->dest_port); + if (c) { + WARN_ON((0 != c->mark) && (0 == mark->mark)); + c->mark = mark->mark; + } + spin_unlock_bh(&si->lock); + + if (c) { + DEBUG_TRACE("Matching connection found for mark, " + "setting from %08x to %08x\n", + c->mark, mark->mark); + } +} + +/* + * sfe_ipv6_insert_connection() + * Insert a connection into the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static void sfe_ipv6_insert_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c) +{ + struct sfe_ipv6_connection **hash_head; + struct sfe_ipv6_connection *prev_head; + unsigned int conn_idx; + + /* + * Insert entry into the connection hash. + */ + conn_idx = sfe_ipv6_get_connection_hash(c->protocol, c->src_ip, c->src_port, + c->dest_ip, c->dest_port); + hash_head = &si->conn_hash[conn_idx]; + prev_head = *hash_head; + c->prev = NULL; + if (prev_head) { + prev_head->prev = c; + } + + c->next = prev_head; + *hash_head = c; + + /* + * Insert entry into the "all connections" list. + */ + if (si->all_connections_tail) { + c->all_connections_prev = si->all_connections_tail; + si->all_connections_tail->all_connections_next = c; + } else { + c->all_connections_prev = NULL; + si->all_connections_head = c; + } + + si->all_connections_tail = c; + c->all_connections_next = NULL; + si->num_connections++; + + /* + * Insert the connection match objects too. + */ + sfe_ipv6_insert_connection_match(si, c->original_match); + sfe_ipv6_insert_connection_match(si, c->reply_match); +} + +/* + * sfe_ipv6_remove_connection() + * Remove a sfe_ipv6_connection object from the hash. + * + * On entry we must be holding the lock that protects the hash table. + */ +static void sfe_ipv6_remove_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c) +{ + /* + * Remove the connection match objects. + */ + sfe_ipv6_remove_connection_match(si, c->reply_match); + sfe_ipv6_remove_connection_match(si, c->original_match); + + /* + * Unlink the connection. + */ + if (c->prev) { + c->prev->next = c->next; + } else { + unsigned int conn_idx = sfe_ipv6_get_connection_hash(c->protocol, c->src_ip, c->src_port, + c->dest_ip, c->dest_port); + si->conn_hash[conn_idx] = c->next; + } + + if (c->next) { + c->next->prev = c->prev; + } + + /* + * Unlink connection from all_connections list + */ + if (c->all_connections_prev) { + c->all_connections_prev->all_connections_next = c->all_connections_next; + } else { + si->all_connections_head = c->all_connections_next; + } + + if (c->all_connections_next) { + c->all_connections_next->all_connections_prev = c->all_connections_prev; + } else { + si->all_connections_tail = c->all_connections_prev; + } + + si->num_connections--; +} + +/* + * sfe_ipv6_gen_sync_connection() + * Sync a connection. + * + * On entry to this function we expect that the lock for the connection is either + * already held or isn't required. + */ +static void sfe_ipv6_gen_sync_connection(struct sfe_ipv6 *si, struct sfe_ipv6_connection *c, + struct sfe_connection_sync *sis, sfe_sync_reason_t reason, + u64 now_jiffies) +{ + struct sfe_ipv6_connection_match *original_cm; + struct sfe_ipv6_connection_match *reply_cm; + + /* + * Fill in the update message. + */ + sis->is_v6 = 1; + sis->protocol = c->protocol; + sis->src_ip.ip6[0] = c->src_ip[0]; + sis->src_ip_xlate.ip6[0] = c->src_ip_xlate[0]; + sis->dest_ip.ip6[0] = c->dest_ip[0]; + sis->dest_ip_xlate.ip6[0] = c->dest_ip_xlate[0]; + sis->src_port = c->src_port; + sis->src_port_xlate = c->src_port_xlate; + sis->dest_port = c->dest_port; + sis->dest_port_xlate = c->dest_port_xlate; + + original_cm = c->original_match; + reply_cm = c->reply_match; + sis->src_td_max_window = original_cm->protocol_state.tcp.max_win; + sis->src_td_end = original_cm->protocol_state.tcp.end; + sis->src_td_max_end = original_cm->protocol_state.tcp.max_end; + sis->dest_td_max_window = reply_cm->protocol_state.tcp.max_win; + sis->dest_td_end = reply_cm->protocol_state.tcp.end; + sis->dest_td_max_end = reply_cm->protocol_state.tcp.max_end; + + sis->src_new_packet_count = original_cm->rx_packet_count; + sis->src_new_byte_count = original_cm->rx_byte_count; + sis->dest_new_packet_count = reply_cm->rx_packet_count; + sis->dest_new_byte_count = reply_cm->rx_byte_count; + + sfe_ipv6_connection_match_update_summary_stats(original_cm); + sfe_ipv6_connection_match_update_summary_stats(reply_cm); + + sis->src_dev = original_cm->match_dev; + sis->src_packet_count = original_cm->rx_packet_count64; + sis->src_byte_count = original_cm->rx_byte_count64; + + sis->dest_dev = reply_cm->match_dev; + sis->dest_packet_count = reply_cm->rx_packet_count64; + sis->dest_byte_count = reply_cm->rx_byte_count64; + + sis->reason = reason; + + /* + * Get the time increment since our last sync. + */ + sis->delta_jiffies = now_jiffies - c->last_sync_jiffies; + c->last_sync_jiffies = now_jiffies; +} + +/* + * sfe_ipv6_flush_connection() + * Flush a connection and free all associated resources. + * + * We need to be called with bottom halves disabled locally as we need to acquire + * the connection hash lock and release it again. In general we're actually called + * from within a BH and so we're fine, but we're also called when connections are + * torn down. + */ +static void sfe_ipv6_flush_connection(struct sfe_ipv6 *si, + struct sfe_ipv6_connection *c, + sfe_sync_reason_t reason) +{ + struct sfe_connection_sync sis; + u64 now_jiffies; + sfe_sync_rule_callback_t sync_rule_callback; + + rcu_read_lock(); + spin_lock_bh(&si->lock); + si->connection_flushes++; + sync_rule_callback = rcu_dereference(si->sync_rule_callback); + spin_unlock_bh(&si->lock); + + if (sync_rule_callback) { + /* + * Generate a sync message and then sync. + */ + now_jiffies = get_jiffies_64(); + sfe_ipv6_gen_sync_connection(si, c, &sis, reason, now_jiffies); + sync_rule_callback(&sis); + } + + rcu_read_unlock(); + + /* + * Release our hold of the source and dest devices and free the memory + * for our connection objects. + */ + dev_put(c->original_dev); + dev_put(c->reply_dev); + kfree(c->original_match); + kfree(c->reply_match); + kfree(c); +} + +/* + * sfe_ipv6_recv_udp() + * Handle UDP packet receives and forwarding. + */ +static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl, bool flush_on_find) +{ + struct sfe_ipv6_udp_hdr *udph; + struct sfe_ipv6_addr *src_ip; + struct sfe_ipv6_addr *dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv6_connection_match *cm; + struct net_device *xmit_dev; + + /* + * Is our packet too short to contain a valid UDP header? + */ + if (!pskb_may_pull(skb, (sizeof(struct sfe_ipv6_udp_hdr) + ihl))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for UDP header\n"); + return 0; + } + + /* + * Read the IP address and port information. Read the IP header data first + * because we've almost certainly got that in the cache. We may not yet have + * the UDP header cached though so allow more time for any prefetching. + */ + src_ip = &iph->saddr; + dest_ip = &iph->daddr; + + udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); + src_port = udph->source; + dest_port = udph->dest; + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. + */ +#ifdef CONFIG_NF_FLOW_COOKIE + cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; + if (unlikely(!cm)) { + cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); + } +#else + cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port); +#endif + if (unlikely(!cm)) { + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_NO_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found\n"); + return 0; + } + + /* + * If our packet has beern marked as "flush on find" we can't actually + * forward it in the fast path, but now that we've found an associated + * connection we can flush that out before we process the packet. + */ + if (unlikely(flush_on_find)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("flush on find\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + +#ifdef CONFIG_XFRM + /* + * We can't accelerate the flow on this direction, just let it go + * through the slow path. + */ + if (unlikely(!cm->flow_accel)) { + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } +#endif + + /* + * Does our hop_limit allow forwarding? + */ + if (unlikely(iph->hop_limit < 2)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_SMALL_TTL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("hop_limit too low\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * If our packet is larger than the MTU of the transmit interface then + * we can't forward it easily. + */ + if (unlikely(len > cm->xmit_dev_mtu)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("larger than mtu\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * From this point on we're good to modify the packet. + */ + + /* + * Check if skb was cloned. If it was, unshare it. Because + * the data area is going to be written in this path and we don't want to + * change the cloned skb's data section. + */ + if (unlikely(skb_cloned(skb))) { + DEBUG_TRACE("%p: skb is a cloned skb\n", skb); + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + DEBUG_WARN("Failed to unshare the cloned skb\n"); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + return 0; + } + + /* + * Update the iph and udph pointers with the unshared skb's data area. + */ + iph = (struct sfe_ipv6_ip_hdr *)skb->data; + udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); + } + + /* + * Update DSCP + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { + sfe_ipv6_change_dsfield(iph, cm->dscp); + } + + /* + * Decrement our hop_limit. + */ + iph->hop_limit -= 1; + + /* + * Do we have to perform translations of the source address/port? + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) { + u16 udp_csum; + + iph->saddr = cm->xlate_src_ip[0]; + udph->source = cm->xlate_src_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + udp_csum = udph->check; + if (likely(udp_csum)) { + u32 sum = udp_csum + cm->xlate_src_csum_adjustment; + sum = (sum & 0xffff) + (sum >> 16); + udph->check = (u16)sum; + } + } + + /* + * Do we have to perform translations of the destination address/port? + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST)) { + u16 udp_csum; + + iph->daddr = cm->xlate_dest_ip[0]; + udph->dest = cm->xlate_dest_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + udp_csum = udph->check; + if (likely(udp_csum)) { + u32 sum = udp_csum + cm->xlate_dest_csum_adjustment; + sum = (sum & 0xffff) + (sum >> 16); + udph->check = (u16)sum; + } + } + + /* + * Update traffic stats. + */ + cm->rx_packet_count++; + cm->rx_byte_count += len; + + /* + * If we're not already on the active list then insert ourselves at the tail + * of the current list. + */ + if (unlikely(!cm->active)) { + cm->active = true; + cm->active_prev = si->active_tail; + if (likely(si->active_tail)) { + si->active_tail->active_next = cm; + } else { + si->active_head = cm; + } + si->active_tail = cm; + } + + xmit_dev = cm->xmit_dev; + skb->dev = xmit_dev; + + /* + * Check to see if we need to write a header. + */ + if (likely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { + if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { + dev_hard_header(skb, xmit_dev, ETH_P_IPV6, + cm->xmit_dest_mac, cm->xmit_src_mac, len); + } else { + /* + * For the simple case we write this really fast. + */ + struct sfe_ipv6_eth_hdr *eth = (struct sfe_ipv6_eth_hdr *)__skb_push(skb, ETH_HLEN); + eth->h_proto = htons(ETH_P_IPV6); + eth->h_dest[0] = cm->xmit_dest_mac[0]; + eth->h_dest[1] = cm->xmit_dest_mac[1]; + eth->h_dest[2] = cm->xmit_dest_mac[2]; + eth->h_source[0] = cm->xmit_src_mac[0]; + eth->h_source[1] = cm->xmit_src_mac[1]; + eth->h_source[2] = cm->xmit_src_mac[2]; + } + } + + /* + * Update priority of skb. + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { + skb->priority = cm->priority; + } + + /* + * Mark outgoing packet. + */ + skb->mark = cm->connection->mark; + if (skb->mark) { + DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + } + + si->packets_forwarded++; + spin_unlock_bh(&si->lock); + + /* + * We're going to check for GSO flags when we transmit the packet so + * start fetching the necessary cache line now. + */ + prefetch(skb_shinfo(skb)); + + /* + * Mark that this packet has been fast forwarded. + */ + skb->fast_forwarded = 1; + + /* + * Send the packet on its way. + */ + dev_queue_xmit(skb); + + return 1; +} + +/* + * sfe_ipv6_process_tcp_option_sack() + * Parse TCP SACK option and update ack according + */ +static bool sfe_ipv6_process_tcp_option_sack(const struct sfe_ipv6_tcp_hdr *th, const u32 data_offs, + u32 *ack) +{ + u32 length = sizeof(struct sfe_ipv6_tcp_hdr); + u8 *ptr = (u8 *)th + length; + + /* + * Ignore processing if TCP packet has only TIMESTAMP option. + */ + if (likely(data_offs == length + TCPOLEN_TIMESTAMP + 1 + 1) + && likely(ptr[0] == TCPOPT_NOP) + && likely(ptr[1] == TCPOPT_NOP) + && likely(ptr[2] == TCPOPT_TIMESTAMP) + && likely(ptr[3] == TCPOLEN_TIMESTAMP)) { + return true; + } + + /* + * TCP options. Parse SACK option. + */ + while (length < data_offs) { + u8 size; + u8 kind; + + ptr = (u8 *)th + length; + kind = *ptr; + + /* + * NOP, for padding + * Not in the switch because to fast escape and to not calculate size + */ + if (kind == TCPOPT_NOP) { + length++; + continue; + } + + if (kind == TCPOPT_SACK) { + u32 sack = 0; + u8 re = 1 + 1; + + size = *(ptr + 1); + if ((size < (1 + 1 + TCPOLEN_SACK_PERBLOCK)) + || ((size - (1 + 1)) % (TCPOLEN_SACK_PERBLOCK)) + || (size > (data_offs - length))) { + return false; + } + + re += 4; + while (re < size) { + u32 sack_re; + u8 *sptr = ptr + re; + sack_re = (sptr[0] << 24) | (sptr[1] << 16) | (sptr[2] << 8) | sptr[3]; + if (sack_re > sack) { + sack = sack_re; + } + re += TCPOLEN_SACK_PERBLOCK; + } + if (sack > *ack) { + *ack = sack; + } + length += size; + continue; + } + if (kind == TCPOPT_EOL) { + return true; + } + size = *(ptr + 1); + if (size < 2) { + return false; + } + length += size; + } + + return true; +} + +/* + * sfe_ipv6_recv_tcp() + * Handle TCP packet receives and forwarding. + */ +static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl, bool flush_on_find) +{ + struct sfe_ipv6_tcp_hdr *tcph; + struct sfe_ipv6_addr *src_ip; + struct sfe_ipv6_addr *dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv6_connection_match *cm; + struct sfe_ipv6_connection_match *counter_cm; + u32 flags; + struct net_device *xmit_dev; + + /* + * Is our packet too short to contain a valid UDP header? + */ + if (!pskb_may_pull(skb, (sizeof(struct sfe_ipv6_tcp_hdr) + ihl))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for TCP header\n"); + return 0; + } + + /* + * Read the IP address and port information. Read the IP header data first + * because we've almost certainly got that in the cache. We may not yet have + * the TCP header cached though so allow more time for any prefetching. + */ + src_ip = &iph->saddr; + dest_ip = &iph->daddr; + + tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); + src_port = tcph->source; + dest_port = tcph->dest; + flags = tcp_flag_word(tcph); + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. + */ +#ifdef CONFIG_NF_FLOW_COOKIE + cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match; + if (unlikely(!cm)) { + cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); + } +#else + cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port); +#endif + if (unlikely(!cm)) { + /* + * We didn't get a connection but as TCP is connection-oriented that + * may be because this is a non-fast connection (not running established). + * For diagnostic purposes we differentiate this here. + */ + if (likely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) == TCP_FLAG_ACK)) { + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_FAST_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found - fast flags\n"); + return 0; + } + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NO_CONNECTION_SLOW_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found - slow flags: 0x%x\n", + flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); + return 0; + } + + /* + * If our packet has beern marked as "flush on find" we can't actually + * forward it in the fast path, but now that we've found an associated + * connection we can flush that out before we process the packet. + */ + if (unlikely(flush_on_find)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_IP_OPTIONS_OR_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("flush on find\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + +#ifdef CONFIG_XFRM + /* + * We can't accelerate the flow on this direction, just let it go + * through the slow path. + */ + if (unlikely(!cm->flow_accel)) { + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + return 0; + } +#endif + + /* + * Does our hop_limit allow forwarding? + */ + if (unlikely(iph->hop_limit < 2)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_TTL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("hop_limit too low\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * If our packet is larger than the MTU of the transmit interface then + * we can't forward it easily. + */ + if (unlikely((len > cm->xmit_dev_mtu) && !skb_is_gso(skb))) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("larger than mtu\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Look at our TCP flags. Anything missing an ACK or that has RST, SYN or FIN + * set is not a fast path packet. + */ + if (unlikely((flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)) != TCP_FLAG_ACK)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_FLAGS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP flags: 0x%x are not fast\n", + flags & (TCP_FLAG_SYN | TCP_FLAG_RST | TCP_FLAG_FIN | TCP_FLAG_ACK)); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + counter_cm = cm->counter_match; + + /* + * Are we doing sequence number checking? + */ + if (likely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK))) { + u32 seq; + u32 ack; + u32 sack; + u32 data_offs; + u32 end; + u32 left_edge; + u32 scaled_win; + u32 max_end; + + /* + * Is our sequence fully past the right hand edge of the window? + */ + seq = ntohl(tcph->seq); + if (unlikely((s32)(seq - (cm->protocol_state.tcp.max_end + 1)) > 0)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("seq: %u exceeds right edge: %u\n", + seq, cm->protocol_state.tcp.max_end + 1); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Check that our TCP data offset isn't too short. + */ + data_offs = tcph->doff << 2; + if (unlikely(data_offs < sizeof(struct sfe_ipv6_tcp_hdr))) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP data offset: %u, too small\n", data_offs); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Update ACK according to any SACK option. + */ + ack = ntohl(tcph->ack_seq); + sack = ack; + if (unlikely(!sfe_ipv6_process_tcp_option_sack(tcph, data_offs, &sack))) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_BAD_SACK]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP option SACK size is wrong\n"); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Check that our TCP data offset isn't past the end of the packet. + */ + data_offs += sizeof(struct sfe_ipv6_ip_hdr); + if (unlikely(len < data_offs)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("TCP data offset: %u, past end of packet: %u\n", + data_offs, len); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + end = seq + len - data_offs; + + /* + * Is our sequence fully before the left hand edge of the window? + */ + if (unlikely((s32)(end - (cm->protocol_state.tcp.end + - counter_cm->protocol_state.tcp.max_win - 1)) < 0)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("seq: %u before left edge: %u\n", + end, cm->protocol_state.tcp.end - counter_cm->protocol_state.tcp.max_win - 1); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Are we acking data that is to the right of what has been sent? + */ + if (unlikely((s32)(sack - (counter_cm->protocol_state.tcp.end + 1)) > 0)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ack: %u exceeds right edge: %u\n", + sack, counter_cm->protocol_state.tcp.end + 1); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Is our ack too far before the left hand edge of the window? + */ + left_edge = counter_cm->protocol_state.tcp.end + - cm->protocol_state.tcp.max_win + - SFE_IPV6_TCP_MAX_ACK_WINDOW + - 1; + if (unlikely((s32)(sack - left_edge) < 0)) { + struct sfe_ipv6_connection *c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("ack: %u before left edge: %u\n", sack, left_edge); + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; + } + + /* + * Have we just seen the largest window size yet for this connection? If yes + * then we need to record the new value. + */ + scaled_win = ntohs(tcph->window) << cm->protocol_state.tcp.win_scale; + scaled_win += (sack - ack); + if (unlikely(cm->protocol_state.tcp.max_win < scaled_win)) { + cm->protocol_state.tcp.max_win = scaled_win; + } + + /* + * If our sequence and/or ack numbers have advanced then record the new state. + */ + if (likely((s32)(end - cm->protocol_state.tcp.end) >= 0)) { + cm->protocol_state.tcp.end = end; + } + + max_end = sack + scaled_win; + if (likely((s32)(max_end - counter_cm->protocol_state.tcp.max_end) >= 0)) { + counter_cm->protocol_state.tcp.max_end = max_end; + } + } + + /* + * From this point on we're good to modify the packet. + */ + + /* + * Check if skb was cloned. If it was, unshare it. Because + * the data area is going to be written in this path and we don't want to + * change the cloned skb's data section. + */ + if (unlikely(skb_cloned(skb))) { + DEBUG_TRACE("%p: skb is a cloned skb\n", skb); + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + DEBUG_WARN("Failed to unshare the cloned skb\n"); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + return 0; + } + + /* + * Update the iph and tcph pointers with the unshared skb's data area. + */ + iph = (struct sfe_ipv6_ip_hdr *)skb->data; + tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); + } + + /* + * Update DSCP + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK)) { + sfe_ipv6_change_dsfield(iph, cm->dscp); + } + + /* + * Decrement our hop_limit. + */ + iph->hop_limit -= 1; + + /* + * Do we have to perform translations of the source address/port? + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) { + u16 tcp_csum; + u32 sum; + + iph->saddr = cm->xlate_src_ip[0]; + tcph->source = cm->xlate_src_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + tcp_csum = tcph->check; + sum = tcp_csum + cm->xlate_src_csum_adjustment; + sum = (sum & 0xffff) + (sum >> 16); + tcph->check = (u16)sum; + } + + /* + * Do we have to perform translations of the destination address/port? + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST)) { + u16 tcp_csum; + u32 sum; + + iph->daddr = cm->xlate_dest_ip[0]; + tcph->dest = cm->xlate_dest_port; + + /* + * Do we have a non-zero UDP checksum? If we do then we need + * to update it. + */ + tcp_csum = tcph->check; + sum = tcp_csum + cm->xlate_dest_csum_adjustment; + sum = (sum & 0xffff) + (sum >> 16); + tcph->check = (u16)sum; + } + + /* + * Update traffic stats. + */ + cm->rx_packet_count++; + cm->rx_byte_count += len; + + /* + * If we're not already on the active list then insert ourselves at the tail + * of the current list. + */ + if (unlikely(!cm->active)) { + cm->active = true; + cm->active_prev = si->active_tail; + if (likely(si->active_tail)) { + si->active_tail->active_next = cm; + } else { + si->active_head = cm; + } + si->active_tail = cm; + } + + xmit_dev = cm->xmit_dev; + skb->dev = xmit_dev; + + /* + * Check to see if we need to write a header. + */ + if (likely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR)) { + if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR))) { + dev_hard_header(skb, xmit_dev, ETH_P_IPV6, + cm->xmit_dest_mac, cm->xmit_src_mac, len); + } else { + /* + * For the simple case we write this really fast. + */ + struct sfe_ipv6_eth_hdr *eth = (struct sfe_ipv6_eth_hdr *)__skb_push(skb, ETH_HLEN); + eth->h_proto = htons(ETH_P_IPV6); + eth->h_dest[0] = cm->xmit_dest_mac[0]; + eth->h_dest[1] = cm->xmit_dest_mac[1]; + eth->h_dest[2] = cm->xmit_dest_mac[2]; + eth->h_source[0] = cm->xmit_src_mac[0]; + eth->h_source[1] = cm->xmit_src_mac[1]; + eth->h_source[2] = cm->xmit_src_mac[2]; + } + } + + /* + * Update priority of skb. + */ + if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK)) { + skb->priority = cm->priority; + } + + /* + * Mark outgoing packet + */ + skb->mark = cm->connection->mark; + if (skb->mark) { + DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + } + + si->packets_forwarded++; + spin_unlock_bh(&si->lock); + + /* + * We're going to check for GSO flags when we transmit the packet so + * start fetching the necessary cache line now. + */ + prefetch(skb_shinfo(skb)); + + /* + * Mark that this packet has been fast forwarded. + */ + skb->fast_forwarded = 1; + + /* + * Send the packet on its way. + */ + dev_queue_xmit(skb); + + return 1; +} + +/* + * sfe_ipv6_recv_icmp() + * Handle ICMP packet receives. + * + * ICMP packets aren't handled as a "fast path" and always have us process them + * through the default Linux stack. What we do need to do is look for any errors + * about connections we are handling in the fast path. If we find any such + * connections then we want to flush their state so that the ICMP error path + * within Linux has all of the correct state should it need it. + */ +static int sfe_ipv6_recv_icmp(struct sfe_ipv6 *si, struct sk_buff *skb, struct net_device *dev, + unsigned int len, struct sfe_ipv6_ip_hdr *iph, unsigned int ihl) +{ + struct icmp6hdr *icmph; + struct sfe_ipv6_ip_hdr *icmp_iph; + struct sfe_ipv6_udp_hdr *icmp_udph; + struct sfe_ipv6_tcp_hdr *icmp_tcph; + struct sfe_ipv6_addr *src_ip; + struct sfe_ipv6_addr *dest_ip; + __be16 src_port; + __be16 dest_port; + struct sfe_ipv6_connection_match *cm; + struct sfe_ipv6_connection *c; + u8 next_hdr; + + /* + * Is our packet too short to contain a valid ICMP header? + */ + len -= ihl; + if (!pskb_may_pull(skb, ihl + sizeof(struct icmp6hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("packet too short for ICMP header\n"); + return 0; + } + + /* + * We only handle "destination unreachable" and "time exceeded" messages. + */ + icmph = (struct icmp6hdr *)(skb->data + ihl); + if ((icmph->icmp6_type != ICMPV6_DEST_UNREACH) + && (icmph->icmp6_type != ICMPV6_TIME_EXCEED)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("unhandled ICMP type: 0x%x\n", icmph->icmp6_type); + return 0; + } + + /* + * Do we have the full embedded IP header? + * We should have 8 bytes of next L4 header - that's enough to identify + * the connection. + */ + len -= sizeof(struct icmp6hdr); + ihl += sizeof(struct icmp6hdr); + if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ip_hdr) + sizeof(struct sfe_ipv6_ext_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Embedded IP header not complete\n"); + return 0; + } + + /* + * Is our embedded IP version wrong? + */ + icmp_iph = (struct sfe_ipv6_ip_hdr *)(icmph + 1); + if (unlikely(icmp_iph->version != 6)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_NON_V6]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("IP version: %u\n", icmp_iph->version); + return 0; + } + + len -= sizeof(struct sfe_ipv6_ip_hdr); + ihl += sizeof(struct sfe_ipv6_ip_hdr); + next_hdr = icmp_iph->nexthdr; + while (unlikely(sfe_ipv6_is_ext_hdr(next_hdr))) { + struct sfe_ipv6_ext_hdr *ext_hdr; + unsigned int ext_hdr_len; + + ext_hdr = (struct sfe_ipv6_ext_hdr *)(skb->data + ihl); + if (next_hdr == SFE_IPV6_EXT_HDR_FRAG) { + struct sfe_ipv6_frag_hdr *frag_hdr = (struct sfe_ipv6_frag_hdr *)ext_hdr; + unsigned int frag_off = ntohs(frag_hdr->frag_off); + + if (frag_off & SFE_IPV6_FRAG_OFFSET) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("non-initial fragment\n"); + return 0; + } + } + + ext_hdr_len = ext_hdr->hdr_len; + ext_hdr_len <<= 3; + ext_hdr_len += sizeof(struct sfe_ipv6_ext_hdr); + len -= ext_hdr_len; + ihl += ext_hdr_len; + /* + * We should have 8 bytes of next header - that's enough to identify + * the connection. + */ + if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("extension header %d not completed\n", next_hdr); + return 0; + } + + next_hdr = ext_hdr->next_hdr; + } + + /* + * Handle the embedded transport layer header. + */ + switch (next_hdr) { + case IPPROTO_UDP: + icmp_udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl); + src_port = icmp_udph->source; + dest_port = icmp_udph->dest; + break; + + case IPPROTO_TCP: + icmp_tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl); + src_port = icmp_tcph->source; + dest_port = icmp_tcph->dest; + break; + + default: + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("Unhandled embedded IP protocol: %u\n", next_hdr); + return 0; + } + + src_ip = &icmp_iph->saddr; + dest_ip = &icmp_iph->daddr; + + spin_lock_bh(&si->lock); + + /* + * Look for a connection match. Note that we reverse the source and destination + * here because our embedded message contains a packet that was sent in the + * opposite direction to the one in which we just received it. It will have + * been sent on the interface from which we received it though so that's still + * ok to use. + */ + cm = sfe_ipv6_find_connection_match(si, dev, icmp_iph->nexthdr, dest_ip, dest_port, src_ip, src_port); + if (unlikely(!cm)) { + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_NO_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("no connection found\n"); + return 0; + } + + /* + * We found a connection so now remove it from the connection list and flush + * its state. + */ + c = cm->connection; + sfe_ipv6_remove_connection(si, c); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_ICMP_FLUSHED_CONNECTION]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH); + return 0; +} + +/* + * sfe_ipv6_recv() + * Handle packet receives and forwaring. + * + * Returns 1 if the packet is forwarded or 0 if it isn't. + */ +int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb) +{ + struct sfe_ipv6 *si = &__si6; + unsigned int len; + unsigned int payload_len; + unsigned int ihl = sizeof(struct sfe_ipv6_ip_hdr); + bool flush_on_find = false; + struct sfe_ipv6_ip_hdr *iph; + u8 next_hdr; + + /* + * Check that we have space for an IP header and an uplayer header here. + */ + len = skb->len; + if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("len: %u is too short\n", len); + return 0; + } + + /* + * Is our IP version wrong? + */ + iph = (struct sfe_ipv6_ip_hdr *)skb->data; + if (unlikely(iph->version != 6)) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_V6]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("IP version: %u\n", iph->version); + return 0; + } + + /* + * Does our datagram fit inside the skb? + */ + payload_len = ntohs(iph->payload_len); + if (unlikely(payload_len > (len - ihl))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("payload_len: %u, exceeds len: %u\n", payload_len, (len - sizeof(struct sfe_ipv6_ip_hdr))); + return 0; + } + + next_hdr = iph->nexthdr; + while (unlikely(sfe_ipv6_is_ext_hdr(next_hdr))) { + struct sfe_ipv6_ext_hdr *ext_hdr; + unsigned int ext_hdr_len; + + ext_hdr = (struct sfe_ipv6_ext_hdr *)(skb->data + ihl); + if (next_hdr == SFE_IPV6_EXT_HDR_FRAG) { + struct sfe_ipv6_frag_hdr *frag_hdr = (struct sfe_ipv6_frag_hdr *)ext_hdr; + unsigned int frag_off = ntohs(frag_hdr->frag_off); + + if (frag_off & SFE_IPV6_FRAG_OFFSET) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("non-initial fragment\n"); + return 0; + } + } + + ext_hdr_len = ext_hdr->hdr_len; + ext_hdr_len <<= 3; + ext_hdr_len += sizeof(struct sfe_ipv6_ext_hdr); + ihl += ext_hdr_len; + if (!pskb_may_pull(skb, ihl + sizeof(struct sfe_ipv6_ext_hdr))) { + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("extension header %d not completed\n", next_hdr); + return 0; + } + + flush_on_find = true; + next_hdr = ext_hdr->next_hdr; + } + + if (IPPROTO_UDP == next_hdr) { + return sfe_ipv6_recv_udp(si, skb, dev, len, iph, ihl, flush_on_find); + } + + if (IPPROTO_TCP == next_hdr) { + return sfe_ipv6_recv_tcp(si, skb, dev, len, iph, ihl, flush_on_find); + } + + if (IPPROTO_ICMPV6 == next_hdr) { + return sfe_ipv6_recv_icmp(si, skb, dev, len, iph, ihl); + } + + spin_lock_bh(&si->lock); + si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("not UDP, TCP or ICMP: %u\n", next_hdr); + return 0; +} + +/* + * sfe_ipv6_update_tcp_state() + * update TCP window variables. + */ +static void +sfe_ipv6_update_tcp_state(struct sfe_ipv6_connection *c, + struct sfe_connection_create *sic) +{ + struct sfe_ipv6_connection_match *orig_cm; + struct sfe_ipv6_connection_match *repl_cm; + struct sfe_ipv6_tcp_connection_match *orig_tcp; + struct sfe_ipv6_tcp_connection_match *repl_tcp; + + orig_cm = c->original_match; + repl_cm = c->reply_match; + orig_tcp = &orig_cm->protocol_state.tcp; + repl_tcp = &repl_cm->protocol_state.tcp; + + /* update orig */ + if (orig_tcp->max_win < sic->src_td_max_window) { + orig_tcp->max_win = sic->src_td_max_window; + } + if ((s32)(orig_tcp->end - sic->src_td_end) < 0) { + orig_tcp->end = sic->src_td_end; + } + if ((s32)(orig_tcp->max_end - sic->src_td_max_end) < 0) { + orig_tcp->max_end = sic->src_td_max_end; + } + + /* update reply */ + if (repl_tcp->max_win < sic->dest_td_max_window) { + repl_tcp->max_win = sic->dest_td_max_window; + } + if ((s32)(repl_tcp->end - sic->dest_td_end) < 0) { + repl_tcp->end = sic->dest_td_end; + } + if ((s32)(repl_tcp->max_end - sic->dest_td_max_end) < 0) { + repl_tcp->max_end = sic->dest_td_max_end; + } + + /* update match flags */ + orig_cm->flags &= ~SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + repl_cm->flags &= ~SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { + orig_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + repl_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + } +} + +/* + * sfe_ipv6_update_protocol_state() + * update protocol specified state machine. + */ +static void +sfe_ipv6_update_protocol_state(struct sfe_ipv6_connection *c, + struct sfe_connection_create *sic) +{ + switch (sic->protocol) { + case IPPROTO_TCP: + sfe_ipv6_update_tcp_state(c, sic); + break; + } +} + +/* + * sfe_ipv6_update_rule() + * update forwarding rule after rule is created. + */ +void sfe_ipv6_update_rule(struct sfe_connection_create *sic) +{ + struct sfe_ipv6_connection *c; + struct sfe_ipv6 *si = &__si6; + + spin_lock_bh(&si->lock); + + c = sfe_ipv6_find_connection(si, + sic->protocol, + sic->src_ip.ip6, + sic->src_port, + sic->dest_ip.ip6, + sic->dest_port); + if (c != NULL) { + sfe_ipv6_update_protocol_state(c, sic); + } + + spin_unlock_bh(&si->lock); +} + +/* + * sfe_ipv6_create_rule() + * Create a forwarding rule. + */ +int sfe_ipv6_create_rule(struct sfe_connection_create *sic) +{ + struct sfe_ipv6 *si = &__si6; + struct sfe_ipv6_connection *c; + struct sfe_ipv6_connection_match *original_cm; + struct sfe_ipv6_connection_match *reply_cm; + struct net_device *dest_dev; + struct net_device *src_dev; + + dest_dev = sic->dest_dev; + src_dev = sic->src_dev; + + if (unlikely((dest_dev->reg_state != NETREG_REGISTERED) || + (src_dev->reg_state != NETREG_REGISTERED))) { + return -EINVAL; + } + + spin_lock_bh(&si->lock); + si->connection_create_requests++; + + /* + * Check to see if there is already a flow that matches the rule we're + * trying to create. If there is then we can't create a new one. + */ + c = sfe_ipv6_find_connection(si, + sic->protocol, + sic->src_ip.ip6, + sic->src_port, + sic->dest_ip.ip6, + sic->dest_port); + if (c != NULL) { + si->connection_create_collisions++; + + /* + * If we already have the flow then it's likely that this + * request to create the connection rule contains more + * up-to-date information. Check and update accordingly. + */ + sfe_ipv6_update_protocol_state(c, sic); + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("connection already exists - mark: %08x, p: %d\n" + " s: %s:%pM:%pI6:%u, d: %s:%pM:%pI6:%u\n", + sic->mark, sic->protocol, + sic->src_dev->name, sic->src_mac, sic->src_ip.ip6, ntohs(sic->src_port), + sic->dest_dev->name, sic->dest_mac, sic->dest_ip.ip6, ntohs(sic->dest_port)); + return -EADDRINUSE; + } + + /* + * Allocate the various connection tracking objects. + */ + c = (struct sfe_ipv6_connection *)kmalloc(sizeof(struct sfe_ipv6_connection), GFP_ATOMIC); + if (unlikely(!c)) { + spin_unlock_bh(&si->lock); + return -ENOMEM; + } + + original_cm = (struct sfe_ipv6_connection_match *)kmalloc(sizeof(struct sfe_ipv6_connection_match), GFP_ATOMIC); + if (unlikely(!original_cm)) { + spin_unlock_bh(&si->lock); + kfree(c); + return -ENOMEM; + } + + reply_cm = (struct sfe_ipv6_connection_match *)kmalloc(sizeof(struct sfe_ipv6_connection_match), GFP_ATOMIC); + if (unlikely(!reply_cm)) { + spin_unlock_bh(&si->lock); + kfree(original_cm); + kfree(c); + return -ENOMEM; + } + + /* + * Fill in the "original" direction connection matching object. + * Note that the transmit MAC address is "dest_mac_xlate" because + * we always know both ends of a connection by their translated + * addresses and not their public addresses. + */ + original_cm->match_dev = src_dev; + original_cm->match_protocol = sic->protocol; + original_cm->match_src_ip[0] = sic->src_ip.ip6[0]; + original_cm->match_src_port = sic->src_port; + original_cm->match_dest_ip[0] = sic->dest_ip.ip6[0]; + original_cm->match_dest_port = sic->dest_port; + original_cm->xlate_src_ip[0] = sic->src_ip_xlate.ip6[0]; + original_cm->xlate_src_port = sic->src_port_xlate; + original_cm->xlate_dest_ip[0] = sic->dest_ip_xlate.ip6[0]; + original_cm->xlate_dest_port = sic->dest_port_xlate; + original_cm->rx_packet_count = 0; + original_cm->rx_packet_count64 = 0; + original_cm->rx_byte_count = 0; + original_cm->rx_byte_count64 = 0; + original_cm->xmit_dev = dest_dev; + original_cm->xmit_dev_mtu = sic->dest_mtu; + memcpy(original_cm->xmit_src_mac, dest_dev->dev_addr, ETH_ALEN); + memcpy(original_cm->xmit_dest_mac, sic->dest_mac_xlate, ETH_ALEN); + original_cm->connection = c; + original_cm->counter_match = reply_cm; + original_cm->flags = 0; + if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { + original_cm->priority = sic->src_priority; + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; + } + if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { + original_cm->dscp = sic->src_dscp << SFE_IPV6_DSCP_SHIFT; + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK; + } +#ifdef CONFIG_NF_FLOW_COOKIE + original_cm->flow_cookie = 0; +#endif +#ifdef CONFIG_XFRM + original_cm->flow_accel = sic->original_accel; +#endif + original_cm->active_next = NULL; + original_cm->active_prev = NULL; + original_cm->active = false; + + /* + * For PPP links we don't write an L2 header. For everything else we do. + */ + if (!(dest_dev->flags & IFF_POINTOPOINT)) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; + + /* + * If our dev writes Ethernet headers then we can write a really fast + * version. + */ + if (dest_dev->header_ops) { + if (dest_dev->header_ops->create == eth_header) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; + } + } + } + + /* + * Fill in the "reply" direction connection matching object. + */ + reply_cm->match_dev = dest_dev; + reply_cm->match_protocol = sic->protocol; + reply_cm->match_src_ip[0] = sic->dest_ip_xlate.ip6[0]; + reply_cm->match_src_port = sic->dest_port_xlate; + reply_cm->match_dest_ip[0] = sic->src_ip_xlate.ip6[0]; + reply_cm->match_dest_port = sic->src_port_xlate; + reply_cm->xlate_src_ip[0] = sic->dest_ip.ip6[0]; + reply_cm->xlate_src_port = sic->dest_port; + reply_cm->xlate_dest_ip[0] = sic->src_ip.ip6[0]; + reply_cm->xlate_dest_port = sic->src_port; + reply_cm->rx_packet_count = 0; + reply_cm->rx_packet_count64 = 0; + reply_cm->rx_byte_count = 0; + reply_cm->rx_byte_count64 = 0; + reply_cm->xmit_dev = src_dev; + reply_cm->xmit_dev_mtu = sic->src_mtu; + memcpy(reply_cm->xmit_src_mac, src_dev->dev_addr, ETH_ALEN); + memcpy(reply_cm->xmit_dest_mac, sic->src_mac, ETH_ALEN); + reply_cm->connection = c; + reply_cm->counter_match = original_cm; + reply_cm->flags = 0; + if (sic->flags & SFE_CREATE_FLAG_REMARK_PRIORITY) { + reply_cm->priority = sic->dest_priority; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_PRIORITY_REMARK; + } + if (sic->flags & SFE_CREATE_FLAG_REMARK_DSCP) { + reply_cm->dscp = sic->dest_dscp << SFE_IPV6_DSCP_SHIFT; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK; + } +#ifdef CONFIG_NF_FLOW_COOKIE + reply_cm->flow_cookie = 0; +#endif +#ifdef CONFIG_XFRM + reply_cm->flow_accel = sic->reply_accel; +#endif + reply_cm->active_next = NULL; + reply_cm->active_prev = NULL; + reply_cm->active = false; + + /* + * For PPP links we don't write an L2 header. For everything else we do. + */ + if (!(src_dev->flags & IFF_POINTOPOINT)) { + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_L2_HDR; + + /* + * If our dev writes Ethernet headers then we can write a really fast + * version. + */ + if (src_dev->header_ops) { + if (src_dev->header_ops->create == eth_header) { + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_WRITE_FAST_ETH_HDR; + } + } + } + + + if (!sfe_ipv6_addr_equal(sic->dest_ip.ip6, sic->dest_ip_xlate.ip6) || sic->dest_port != sic->dest_port_xlate) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC; + } + + if (!sfe_ipv6_addr_equal(sic->src_ip.ip6, sic->src_ip_xlate.ip6) || sic->src_port != sic->src_port_xlate) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST; + } + + c->protocol = sic->protocol; + c->src_ip[0] = sic->src_ip.ip6[0]; + c->src_ip_xlate[0] = sic->src_ip_xlate.ip6[0]; + c->src_port = sic->src_port; + c->src_port_xlate = sic->src_port_xlate; + c->original_dev = src_dev; + c->original_match = original_cm; + c->dest_ip[0] = sic->dest_ip.ip6[0]; + c->dest_ip_xlate[0] = sic->dest_ip_xlate.ip6[0]; + c->dest_port = sic->dest_port; + c->dest_port_xlate = sic->dest_port_xlate; + c->reply_dev = dest_dev; + c->reply_match = reply_cm; + c->mark = sic->mark; + c->debug_read_seq = 0; + c->last_sync_jiffies = get_jiffies_64(); + + /* + * Take hold of our source and dest devices for the duration of the connection. + */ + dev_hold(c->original_dev); + dev_hold(c->reply_dev); + + /* + * Initialize the protocol-specific information that we track. + */ + switch (sic->protocol) { + case IPPROTO_TCP: + original_cm->protocol_state.tcp.win_scale = sic->src_td_window_scale; + original_cm->protocol_state.tcp.max_win = sic->src_td_max_window ? sic->src_td_max_window : 1; + original_cm->protocol_state.tcp.end = sic->src_td_end; + original_cm->protocol_state.tcp.max_end = sic->src_td_max_end; + reply_cm->protocol_state.tcp.win_scale = sic->dest_td_window_scale; + reply_cm->protocol_state.tcp.max_win = sic->dest_td_max_window ? sic->dest_td_max_window : 1; + reply_cm->protocol_state.tcp.end = sic->dest_td_end; + reply_cm->protocol_state.tcp.max_end = sic->dest_td_max_end; + if (sic->flags & SFE_CREATE_FLAG_NO_SEQ_CHECK) { + original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_NO_SEQ_CHECK; + } + break; + } + + sfe_ipv6_connection_match_compute_translations(original_cm); + sfe_ipv6_connection_match_compute_translations(reply_cm); + sfe_ipv6_insert_connection(si, c); + + spin_unlock_bh(&si->lock); + + /* + * We have everything we need! + */ + DEBUG_INFO("new connection - mark: %08x, p: %d\n" + " s: %s:%pM(%pM):%pI6(%pI6):%u(%u)\n" + " d: %s:%pM(%pM):%pI6(%pI6):%u(%u)\n", + sic->mark, sic->protocol, + sic->src_dev->name, sic->src_mac, sic->src_mac_xlate, + sic->src_ip.ip6, sic->src_ip_xlate.ip6, ntohs(sic->src_port), ntohs(sic->src_port_xlate), + dest_dev->name, sic->dest_mac, sic->dest_mac_xlate, + sic->dest_ip.ip6, sic->dest_ip_xlate.ip6, ntohs(sic->dest_port), ntohs(sic->dest_port_xlate)); + + return 0; +} + +/* + * sfe_ipv6_destroy_rule() + * Destroy a forwarding rule. + */ +void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid) +{ + struct sfe_ipv6 *si = &__si6; + struct sfe_ipv6_connection *c; + + spin_lock_bh(&si->lock); + si->connection_destroy_requests++; + + /* + * Check to see if we have a flow that matches the rule we're trying + * to destroy. If there isn't then we can't destroy it. + */ + c = sfe_ipv6_find_connection(si, sid->protocol, sid->src_ip.ip6, sid->src_port, + sid->dest_ip.ip6, sid->dest_port); + if (!c) { + si->connection_destroy_misses++; + spin_unlock_bh(&si->lock); + + DEBUG_TRACE("connection does not exist - p: %d, s: %pI6:%u, d: %pI6:%u\n", + sid->protocol, sid->src_ip.ip6, ntohs(sid->src_port), + sid->dest_ip.ip6, ntohs(sid->dest_port)); + return; + } + + /* + * Remove our connection details from the hash tables. + */ + sfe_ipv6_remove_connection(si, c); + spin_unlock_bh(&si->lock); + + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_DESTROY); + + DEBUG_INFO("connection destroyed - p: %d, s: %pI6:%u, d: %pI6:%u\n", + sid->protocol, sid->src_ip.ip6, ntohs(sid->src_port), + sid->dest_ip.ip6, ntohs(sid->dest_port)); +} + +/* + * sfe_ipv6_register_sync_rule_callback() + * Register a callback for rule synchronization. + */ +void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t sync_rule_callback) +{ + struct sfe_ipv6 *si = &__si6; + + spin_lock_bh(&si->lock); + rcu_assign_pointer(si->sync_rule_callback, sync_rule_callback); + spin_unlock_bh(&si->lock); +} + +/* + * sfe_ipv6_get_debug_dev() + */ +static ssize_t sfe_ipv6_get_debug_dev(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sfe_ipv6 *si = &__si6; + ssize_t count; + int num; + + spin_lock_bh(&si->lock); + num = si->debug_dev; + spin_unlock_bh(&si->lock); + + count = snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", num); + return count; +} + +/* + * sfe_ipv6_destroy_all_rules_for_dev() + * Destroy all connections that match a particular device. + * + * If we pass dev as NULL then this destroys all connections. + */ +void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev) +{ + struct sfe_ipv6 *si = &__si6; + struct sfe_ipv6_connection *c; + +another_round: + spin_lock_bh(&si->lock); + + for (c = si->all_connections_head; c; c = c->all_connections_next) { + /* + * Does this connection relate to the device we are destroying? + */ + if (!dev + || (dev == c->original_dev) + || (dev == c->reply_dev)) { + break; + } + } + + if (c) { + sfe_ipv6_remove_connection(si, c); + } + + spin_unlock_bh(&si->lock); + + if (c) { + sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_DESTROY); + goto another_round; + } +} + +/* + * sfe_ipv6_periodic_sync() + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) +static void sfe_ipv6_periodic_sync(struct timer_list *arg) +#else +static void sfe_ipv6_periodic_sync(unsigned long arg) +#endif /*KERNEL_VERSION(4, 15, 0)*/ +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + struct sfe_ipv6 *si = (struct sfe_ipv6 *)arg->cust_data; +#else + struct sfe_ipv6 *si = (struct sfe_ipv6 *)arg; +#endif /*KERNEL_VERSION(4, 15, 0)*/ + u64 now_jiffies; + int quota; + sfe_sync_rule_callback_t sync_rule_callback; + + now_jiffies = get_jiffies_64(); + + rcu_read_lock(); + sync_rule_callback = rcu_dereference(si->sync_rule_callback); + if (!sync_rule_callback) { + rcu_read_unlock(); + goto done; + } + + spin_lock_bh(&si->lock); + sfe_ipv6_update_summary_stats(si); + + /* + * Get an estimate of the number of connections to parse in this sync. + */ + quota = (si->num_connections + 63) / 64; + + /* + * Walk the "active" list and sync the connection state. + */ + while (quota--) { + struct sfe_ipv6_connection_match *cm; + struct sfe_ipv6_connection_match *counter_cm; + struct sfe_ipv6_connection *c; + struct sfe_connection_sync sis; + + cm = si->active_head; + if (!cm) { + break; + } + + /* + * There's a possibility that our counter match is in the active list too. + * If it is then remove it. + */ + counter_cm = cm->counter_match; + if (counter_cm->active) { + counter_cm->active = false; + + /* + * We must have a connection preceding this counter match + * because that's the one that got us to this point, so we don't have + * to worry about removing the head of the list. + */ + counter_cm->active_prev->active_next = counter_cm->active_next; + + if (likely(counter_cm->active_next)) { + counter_cm->active_next->active_prev = counter_cm->active_prev; + } else { + si->active_tail = counter_cm->active_prev; + } + + counter_cm->active_next = NULL; + counter_cm->active_prev = NULL; + } + + /* + * Now remove the head of the active scan list. + */ + cm->active = false; + si->active_head = cm->active_next; + if (likely(cm->active_next)) { + cm->active_next->active_prev = NULL; + } else { + si->active_tail = NULL; + } + cm->active_next = NULL; + + /* + * Sync the connection state. + */ + c = cm->connection; + sfe_ipv6_gen_sync_connection(si, c, &sis, SFE_SYNC_REASON_STATS, now_jiffies); + + /* + * We don't want to be holding the lock when we sync! + */ + spin_unlock_bh(&si->lock); + sync_rule_callback(&sis); + spin_lock_bh(&si->lock); + } + + spin_unlock_bh(&si->lock); + rcu_read_unlock(); + +done: + mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); +} + +/* + * sfe_ipv6_debug_dev_read_start() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + si->debug_read_seq++; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_connections_start() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_connections_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_connections_connection() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_connections_connection(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + struct sfe_ipv6_connection *c; + struct sfe_ipv6_connection_match *original_cm; + struct sfe_ipv6_connection_match *reply_cm; + int bytes_read; + int protocol; + struct net_device *src_dev; + struct sfe_ipv6_addr src_ip; + struct sfe_ipv6_addr src_ip_xlate; + __be16 src_port; + __be16 src_port_xlate; + u64 src_rx_packets; + u64 src_rx_bytes; + struct net_device *dest_dev; + struct sfe_ipv6_addr dest_ip; + struct sfe_ipv6_addr dest_ip_xlate; + __be16 dest_port; + __be16 dest_port_xlate; + u64 dest_rx_packets; + u64 dest_rx_bytes; + u64 last_sync_jiffies; + u32 mark, src_priority, dest_priority, src_dscp, dest_dscp; +#ifdef CONFIG_NF_FLOW_COOKIE + int src_flow_cookie, dst_flow_cookie; +#endif + + spin_lock_bh(&si->lock); + + for (c = si->all_connections_head; c; c = c->all_connections_next) { + if (c->debug_read_seq < si->debug_read_seq) { + c->debug_read_seq = si->debug_read_seq; + break; + } + } + + /* + * If there were no connections then move to the next state. + */ + if (!c) { + spin_unlock_bh(&si->lock); + ws->state++; + return true; + } + + original_cm = c->original_match; + reply_cm = c->reply_match; + + protocol = c->protocol; + src_dev = c->original_dev; + src_ip = c->src_ip[0]; + src_ip_xlate = c->src_ip_xlate[0]; + src_port = c->src_port; + src_port_xlate = c->src_port_xlate; + src_priority = original_cm->priority; + src_dscp = original_cm->dscp >> SFE_IPV6_DSCP_SHIFT; + + sfe_ipv6_connection_match_update_summary_stats(original_cm); + sfe_ipv6_connection_match_update_summary_stats(reply_cm); + + src_rx_packets = original_cm->rx_packet_count64; + src_rx_bytes = original_cm->rx_byte_count64; + dest_dev = c->reply_dev; + dest_ip = c->dest_ip[0]; + dest_ip_xlate = c->dest_ip_xlate[0]; + dest_port = c->dest_port; + dest_port_xlate = c->dest_port_xlate; + dest_priority = reply_cm->priority; + dest_dscp = reply_cm->dscp >> SFE_IPV6_DSCP_SHIFT; + dest_rx_packets = reply_cm->rx_packet_count64; + dest_rx_bytes = reply_cm->rx_byte_count64; + last_sync_jiffies = get_jiffies_64() - c->last_sync_jiffies; + mark = c->mark; +#ifdef CONFIG_NF_FLOW_COOKIE + src_flow_cookie = original_cm->flow_cookie; + dst_flow_cookie = reply_cm->flow_cookie; +#endif + spin_unlock_bh(&si->lock); + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\t\n", + protocol, + src_dev->name, + &src_ip, &src_ip_xlate, + ntohs(src_port), ntohs(src_port_xlate), + src_priority, src_dscp, + src_rx_packets, src_rx_bytes, + dest_dev->name, + &dest_ip, &dest_ip_xlate, + ntohs(dest_port), ntohs(dest_port_xlate), + dest_priority, dest_dscp, + dest_rx_packets, dest_rx_bytes, +#ifdef CONFIG_NF_FLOW_COOKIE + src_flow_cookie, dst_flow_cookie, +#endif + last_sync_jiffies, mark); + + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + return true; +} + +/* + * sfe_ipv6_debug_dev_read_connections_end() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_connections_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_exceptions_start() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_exceptions_start(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_exceptions_exception() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_exceptions_exception(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + u64 ct; + + spin_lock_bh(&si->lock); + ct = si->exception_events64[ws->iter_exception]; + spin_unlock_bh(&si->lock); + + if (ct) { + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, + "\t\t\n", + sfe_ipv6_exception_events_string[ws->iter_exception], + ct); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + } + + ws->iter_exception++; + if (ws->iter_exception >= SFE_IPV6_EXCEPTION_EVENT_LAST) { + ws->iter_exception = 0; + ws->state++; + } + + return true; +} + +/* + * sfe_ipv6_debug_dev_read_exceptions_end() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_exceptions_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_stats() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_stats(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + unsigned int num_connections; + u64 packets_forwarded; + u64 packets_not_forwarded; + u64 connection_create_requests; + u64 connection_create_collisions; + u64 connection_destroy_requests; + u64 connection_destroy_misses; + u64 connection_flushes; + u64 connection_match_hash_hits; + u64 connection_match_hash_reorders; + + spin_lock_bh(&si->lock); + sfe_ipv6_update_summary_stats(si); + + num_connections = si->num_connections; + packets_forwarded = si->packets_forwarded64; + packets_not_forwarded = si->packets_not_forwarded64; + connection_create_requests = si->connection_create_requests64; + connection_create_collisions = si->connection_create_collisions64; + connection_destroy_requests = si->connection_destroy_requests64; + connection_destroy_misses = si->connection_destroy_misses64; + connection_flushes = si->connection_flushes64; + connection_match_hash_hits = si->connection_match_hash_hits64; + connection_match_hash_reorders = si->connection_match_hash_reorders64; + spin_unlock_bh(&si->lock); + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\n", + num_connections, + packets_forwarded, + packets_not_forwarded, + connection_create_requests, + connection_create_collisions, + connection_destroy_requests, + connection_destroy_misses, + connection_flushes, + connection_match_hash_hits, + connection_match_hash_reorders); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * sfe_ipv6_debug_dev_read_end() + * Generate part of the XML output. + */ +static bool sfe_ipv6_debug_dev_read_end(struct sfe_ipv6 *si, char *buffer, char *msg, size_t *length, + int *total_read, struct sfe_ipv6_debug_xml_write_state *ws) +{ + int bytes_read; + + bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\n"); + if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) { + return false; + } + + *length -= bytes_read; + *total_read += bytes_read; + + ws->state++; + return true; +} + +/* + * Array of write functions that write various XML elements that correspond to + * our XML output state machine. + */ +static sfe_ipv6_debug_xml_write_method_t sfe_ipv6_debug_xml_write_methods[SFE_IPV6_DEBUG_XML_STATE_DONE] = { + sfe_ipv6_debug_dev_read_start, + sfe_ipv6_debug_dev_read_connections_start, + sfe_ipv6_debug_dev_read_connections_connection, + sfe_ipv6_debug_dev_read_connections_end, + sfe_ipv6_debug_dev_read_exceptions_start, + sfe_ipv6_debug_dev_read_exceptions_exception, + sfe_ipv6_debug_dev_read_exceptions_end, + sfe_ipv6_debug_dev_read_stats, + sfe_ipv6_debug_dev_read_end, +}; + +/* + * sfe_ipv6_debug_dev_read() + * Send info to userspace upon read request from user + */ +static ssize_t sfe_ipv6_debug_dev_read(struct file *filp, char *buffer, size_t length, loff_t *offset) +{ + char msg[CHAR_DEV_MSG_SIZE]; + int total_read = 0; + struct sfe_ipv6_debug_xml_write_state *ws; + struct sfe_ipv6 *si = &__si6; + + ws = (struct sfe_ipv6_debug_xml_write_state *)filp->private_data; + while ((ws->state != SFE_IPV6_DEBUG_XML_STATE_DONE) && (length > CHAR_DEV_MSG_SIZE)) { + if ((sfe_ipv6_debug_xml_write_methods[ws->state])(si, buffer, msg, &length, &total_read, ws)) { + continue; + } + } + + return total_read; +} + +/* + * sfe_ipv6_debug_dev_write() + * Write to char device resets some stats + */ +static ssize_t sfe_ipv6_debug_dev_write(struct file *filp, const char *buffer, size_t length, loff_t *offset) +{ + struct sfe_ipv6 *si = &__si6; + + spin_lock_bh(&si->lock); + sfe_ipv6_update_summary_stats(si); + + si->packets_forwarded64 = 0; + si->packets_not_forwarded64 = 0; + si->connection_create_requests64 = 0; + si->connection_create_collisions64 = 0; + si->connection_destroy_requests64 = 0; + si->connection_destroy_misses64 = 0; + si->connection_flushes64 = 0; + si->connection_match_hash_hits64 = 0; + si->connection_match_hash_reorders64 = 0; + spin_unlock_bh(&si->lock); + + return length; +} + +/* + * sfe_ipv6_debug_dev_open() + */ +static int sfe_ipv6_debug_dev_open(struct inode *inode, struct file *file) +{ + struct sfe_ipv6_debug_xml_write_state *ws; + + ws = (struct sfe_ipv6_debug_xml_write_state *)file->private_data; + if (ws) { + return 0; + } + + ws = kzalloc(sizeof(struct sfe_ipv6_debug_xml_write_state), GFP_KERNEL); + if (!ws) { + return -ENOMEM; + } + + ws->state = SFE_IPV6_DEBUG_XML_STATE_START; + file->private_data = ws; + + return 0; +} + +/* + * sfe_ipv6_debug_dev_release() + */ +static int sfe_ipv6_debug_dev_release(struct inode *inode, struct file *file) +{ + struct sfe_ipv6_debug_xml_write_state *ws; + + ws = (struct sfe_ipv6_debug_xml_write_state *)file->private_data; + if (ws) { + /* + * We've finished with our output so free the write state. + */ + kfree(ws); + } + + return 0; +} + +/* + * File operations used in the debug char device + */ +static struct file_operations sfe_ipv6_debug_dev_fops = { + .read = sfe_ipv6_debug_dev_read, + .write = sfe_ipv6_debug_dev_write, + .open = sfe_ipv6_debug_dev_open, + .release = sfe_ipv6_debug_dev_release +}; + +#ifdef CONFIG_NF_FLOW_COOKIE +/* + * sfe_ipv6_register_flow_cookie_cb + * register a function in SFE to let SFE use this function to configure flow cookie for a flow + * + * Hardware driver which support flow cookie should register a callback function in SFE. Then SFE + * can use this function to configure flow cookie for a flow. + * return: 0, success; !=0, fail + */ +int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb) +{ + struct sfe_ipv6 *si = &__si6; + + BUG_ON(!cb); + + if (si->flow_cookie_set_func) { + return -1; + } + + rcu_assign_pointer(si->flow_cookie_set_func, cb); + return 0; +} + +/* + * sfe_ipv6_unregister_flow_cookie_cb + * unregister function which is used to configure flow cookie for a flow + * + * return: 0, success; !=0, fail + */ +int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb) +{ + struct sfe_ipv6 *si = &__si6; + + RCU_INIT_POINTER(si->flow_cookie_set_func, NULL); + return 0; +} + +/* + * sfe_ipv6_get_flow_cookie() + */ +static ssize_t sfe_ipv6_get_flow_cookie(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sfe_ipv6 *si = &__si6; + return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", si->flow_cookie_enable); +} + +/* + * sfe_ipv6_set_flow_cookie() + */ +static ssize_t sfe_ipv6_set_flow_cookie(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct sfe_ipv6 *si = &__si6; + strict_strtol(buf, 0, (long int *)&si->flow_cookie_enable); + + return size; +} + +/* + * sysfs attributes. + */ +static const struct device_attribute sfe_ipv6_flow_cookie_attr = + __ATTR(flow_cookie_enable, S_IWUSR | S_IRUGO, sfe_ipv6_get_flow_cookie, sfe_ipv6_set_flow_cookie); +#endif /*CONFIG_NF_FLOW_COOKIE*/ + +/* + * sfe_ipv6_init() + */ +static int __init sfe_ipv6_init(void) +{ + struct sfe_ipv6 *si = &__si6; + int result = -1; + + DEBUG_INFO("SFE IPv6 init\n"); + + /* + * Create sys/sfe_ipv6 + */ + si->sys_sfe_ipv6 = kobject_create_and_add("sfe_ipv6", NULL); + if (!si->sys_sfe_ipv6) { + DEBUG_ERROR("failed to register sfe_ipv6\n"); + goto exit1; + } + + /* + * Create files, one for each parameter supported by this module. + */ + result = sysfs_create_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); + if (result) { + DEBUG_ERROR("failed to register debug dev file: %d\n", result); + goto exit2; + } + +#ifdef CONFIG_NF_FLOW_COOKIE + result = sysfs_create_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); + if (result) { + DEBUG_ERROR("failed to register flow cookie enable file: %d\n", result); + goto exit3; + } +#endif /* CONFIG_NF_FLOW_COOKIE */ + + /* + * Register our debug char device. + */ + result = register_chrdev(0, "sfe_ipv6", &sfe_ipv6_debug_dev_fops); + if (result < 0) { + DEBUG_ERROR("Failed to register chrdev: %d\n", result); + goto exit4; + } + + si->debug_dev = result; + + /* + * Create a timer to handle periodic statistics. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) + timer_setup(&si->timer, sfe_ipv6_periodic_sync, 0); + si->timer.cust_data = (unsigned long)si; +#else + setup_timer(&si->timer, sfe_ipv6_periodic_sync, (unsigned long)si); +#endif /*KERNEL_VERSION(4, 15, 0)*/ + mod_timer(&si->timer, jiffies + ((HZ + 99) / 100)); + + spin_lock_init(&si->lock); + + return 0; + +exit4: +#ifdef CONFIG_NF_FLOW_COOKIE + sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); + +exit3: +#endif /* CONFIG_NF_FLOW_COOKIE */ + sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); + +exit2: + kobject_put(si->sys_sfe_ipv6); + +exit1: + return result; +} + +/* + * sfe_ipv6_exit() + */ +static void __exit sfe_ipv6_exit(void) +{ + struct sfe_ipv6 *si = &__si6; + + DEBUG_INFO("SFE IPv6 exit\n"); + + /* + * Destroy all connections. + */ + sfe_ipv6_destroy_all_rules_for_dev(NULL); + + del_timer_sync(&si->timer); + + unregister_chrdev(si->debug_dev, "sfe_ipv6"); + +#ifdef CONFIG_NF_FLOW_COOKIE + sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr); +#endif /* CONFIG_NF_FLOW_COOKIE */ + sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr); + + kobject_put(si->sys_sfe_ipv6); +} + +module_init(sfe_ipv6_init) +module_exit(sfe_ipv6_exit) + +EXPORT_SYMBOL(sfe_ipv6_recv); +EXPORT_SYMBOL(sfe_ipv6_create_rule); +EXPORT_SYMBOL(sfe_ipv6_destroy_rule); +EXPORT_SYMBOL(sfe_ipv6_destroy_all_rules_for_dev); +EXPORT_SYMBOL(sfe_ipv6_register_sync_rule_callback); +EXPORT_SYMBOL(sfe_ipv6_mark_rule); +EXPORT_SYMBOL(sfe_ipv6_update_rule); +#ifdef CONFIG_NF_FLOW_COOKIE +EXPORT_SYMBOL(sfe_ipv6_register_flow_cookie_cb); +EXPORT_SYMBOL(sfe_ipv6_unregister_flow_cookie_cb); +#endif + +MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv6 support"); +MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/v2ray-core/files/etc/init.d/v2ray b/v2ray-core/files/etc/init.d/v2ray index dfa0f44cb..07d4d311a 100755 --- a/v2ray-core/files/etc/init.d/v2ray +++ b/v2ray-core/files/etc/init.d/v2ray @@ -2081,12 +2081,15 @@ start_instance() { } rules_exist() { - [ -n "$(iptables -t nat -L -n | grep v2r_)" ] && return 0 + [ -n "$(iptables -w -t nat -L -n | grep v2r_)" ] && return 0 return 1 } rules_up() { - rules_exist && return 0 + rules_exist && { + [ -f /bin/blocklanfw ] && /bin/blocklanfw 2>&1 >/dev/null + return 0 + } enabled="0" config_load v2ray config_get enabled main enabled "0" @@ -2098,6 +2101,11 @@ rules_up() { logger -t "v2ray" "Rules UP" add_v2ray_redirect_rules } + [ -f /etc/init.d/omr-bypass ] && { + logger -t "v2ray" "Reload omr-bypass rules" + /etc/init.d/omr-bypass reload_rules + } + [ -f /bin/blocklanfw ] && /bin/blocklanfw 2>&1 >/dev/null } rules_down() { diff --git a/v2ray-core/files/usr/bin/v2ray-rules b/v2ray-core/files/usr/bin/v2ray-rules index f0f3a3811..a169da026 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules +++ b/v2ray-core/files/usr/bin/v2ray-rules @@ -275,7 +275,7 @@ v2r_rules_iptchains_mkprerules() { local proto="$1" if [ -z "$o_ifnames" ]; then - echo "-I PREROUTING 1 -p $proto -j v2r_${rule}_pre_src" + echo "-A PREROUTING -p $proto -j v2r_${rule}_pre_src" else echo $o_ifnames \ | tr ' ' '\n' \ @@ -283,7 +283,25 @@ v2r_rules_iptchains_mkprerules() { fi } +v2r_rules_fw_drop() { + fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "iptables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done + fw3 -4 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "iptables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done +} + v2r_rules_parse_args "$@" #v2r_rules_flush v2r_rules_ipset_init v2r_rules_iptchains_init +v2r_rules_fw_drop \ No newline at end of file diff --git a/v2ray-core/files/usr/bin/v2ray-rules6 b/v2ray-core/files/usr/bin/v2ray-rules6 index 4eee4651a..1cfa891b3 100755 --- a/v2ray-core/files/usr/bin/v2ray-rules6 +++ b/v2ray-core/files/usr/bin/v2ray-rules6 @@ -266,7 +266,7 @@ v2ray_rules6_iptchains_mkprerules() { local proto="$1" if [ -z "$o_ifnames" ]; then - echo "-I PREROUTING 1 -p $proto -j v2r6_${rule}_pre_src" + echo "-A PREROUTING -p $proto -j v2r6_${rule}_pre_src" else echo $o_ifnames \ | tr ' ' '\n' \ @@ -274,7 +274,25 @@ v2ray_rules6_iptchains_mkprerules() { fi } +v2ray_rules6_fw_drop() { + fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j reject/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/reject/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "ip6tables -w -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done + fw3 -6 print 2>/dev/null | awk '/iptables/&&/zone_lan_forward/&&/tcp/&&/-t filter/&&/-j drop/ {for(i=6; i<=NF; i++) { printf "%s ",$i } print "\n" }' | + while IFS=$"\n" read -r c; do + fwrule=$(echo "$c" | sed 's/drop/REDIRECT --to-ports 65535/') + if [ -n "$fwrule" ] && [ -z "$(iptables-save | grep zone_lan_prerouting | grep '${fwrule}')" ]; then + eval "ip6tables -t nat -A zone_lan_prerouting ${fwrule} 2>&1 >/dev/null" + fi + done +} + v2ray_rules6_parse_args "$@" v2ray_rules6_flush v2ray_rules6_ipset_init v2ray_rules6_iptchains_init +v2ray_rules6_fw_drop \ No newline at end of file