Skip to content

Instantly share code, notes, and snippets.

@drdaeman
Last active August 29, 2015 14:02
Show Gist options
  • Save drdaeman/f4884077d338efb72ea4 to your computer and use it in GitHub Desktop.
Save drdaeman/f4884077d338efb72ea4 to your computer and use it in GitHub Desktop.

Revisions

  1. drdaeman revised this gist Jun 9, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions ppp_generic.patch
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    --- drivers/net/ppp/ppp_generic.c 2014-01-20 06:40:07.000000000 +0400
    +++ drivers/net/ppp/ppp_generic.c 2014-06-09 02:46:38.000000000 +0400
    +++ drivers/net/ppp/ppp_generic.c 2014-06-09 14:48:48.000000000 +0400
    @@ -54,6 +54,13 @@
    #include <net/net_namespace.h>
    #include <net/netns/generic.h>
    @@ -49,7 +49,7 @@
    + if (copy_from_user(b, buf, len))
    + return -EFAULT;
    +
    + if (strcmp(b, "debug") == 0) {
    + if (strncmp(b, "debug", len) == 0) {
    + ppp_filter_counters_debug = ~ppp_filter_counters_debug;
    + pr_notice("ppp_filter_counters: debugging %s\n",
    + ppp_filter_counters_debug ? "enabled" : "disabled");
  2. drdaeman created this gist Jun 8, 2014.
    238 changes: 238 additions & 0 deletions ppp_generic.patch
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,238 @@
    --- drivers/net/ppp/ppp_generic.c 2014-01-20 06:40:07.000000000 +0400
    +++ drivers/net/ppp/ppp_generic.c 2014-06-09 02:46:38.000000000 +0400
    @@ -54,6 +54,13 @@
    #include <net/net_namespace.h>
    #include <net/netns/generic.h>

    +#define CONFIG_PPP_FILTER_COUNTERS 1
    +
    +#ifdef CONFIG_PPP_FILTER_COUNTERS
    +#include <linux/proc_fs.h>
    +#include <linux/seq_file.h>
    +#endif
    +
    #define PPP_VERSION "2.4.2"

    /*
    @@ -367,6 +374,179 @@
    #define ppp_unlock(ppp) do { ppp_recv_unlock(ppp); \
    ppp_xmit_unlock(ppp); } while (0)

    +
    +#ifdef CONFIG_PPP_FILTER_COUNTERS
    +#define PPP_FILTER_COUNTERS_MAX 64
    +#define PPP_FILTER_COUNTERS_PROCNAME "ppp_filter_counters"
    +
    +static u32 ppp_filter_counters[PPP_FILTER_COUNTERS_MAX][2];
    +static unsigned int ppp_filter_counters_count;
    +static bool ppp_filter_counters_debug;
    +
    +static ssize_t ppp_filter_counters_proc_write(struct file *fp, const char __user *buf, size_t len, loff_t *ppos) {
    + char b[24];
    + char *str;
    + bool insert = false;
    + u32 ip;
    + unsigned int i, j;
    + u32 ip_byte[4], mask = 0, masklen = 0;
    + loff_t pos = *ppos;
    +
    + if (pos < 0)
    + return -EINVAL;
    + if (pos != 0) {
    + pr_warn("ppp_filter_counters: write from non-zero offset (%lld) is not supported\n", pos);
    + return -EFAULT;
    + }
    + if (len > 20) {
    + pr_warn("ppp_filter_counters: string is too long (%zu)\n", len);
    + return -EFAULT;
    + }
    + if (copy_from_user(b, buf, len))
    + return -EFAULT;
    +
    + if (strcmp(b, "debug") == 0) {
    + ppp_filter_counters_debug = ~ppp_filter_counters_debug;
    + pr_notice("ppp_filter_counters: debugging %s\n",
    + ppp_filter_counters_debug ? "enabled" : "disabled");
    + return len;
    + }
    +
    + if (b[0] == '+') {
    + if (ppp_filter_counters_count < PPP_FILTER_COUNTERS_MAX) {
    + insert = true;
    + } else {
    + pr_warn("ppp_filter_counters: table is full\n");
    + return -EFAULT;
    + }
    + } else if (b[0] == '-') {
    + insert = false;
    + } else {
    + pr_warn("ppp_filter_counters: syntax error, must be (+|-)<IPv4/mask>\n");
    + return -EFAULT;
    + }
    + str = b;
    + str++;
    + b[len] = '\0';
    +
    + sscanf(str, "%d.%d.%d.%d/%d", &ip_byte[3], &ip_byte[2], &ip_byte[1], &ip_byte[0], &masklen);
    + if (ip_byte[3] > 255 || ip_byte[2] > 255 || ip_byte[1] > 255|| ip_byte[0] > 255) {
    + pr_warn("ppp_filter_counters: not a valid IPv4 address\n");
    + return -EFAULT;
    + }
    + ip = (ip_byte[3]<<24) | (ip_byte[2]<<16) | (ip_byte[1]<<8) | (ip_byte[0]);
    + if (masklen > 32 || masklen < 0) {
    + pr_warn("ppp_filter_counters: invalid netmask (%d)\n", masklen);
    + return -EFAULT;
    + }
    + mask = 0xffffffff << (32 - masklen);
    +
    + if (ip != 0 && mask) {
    + if (insert) {
    + for (i = 0; i < ppp_filter_counters_count; i++) {
    + if (ip == ppp_filter_counters[i][0] && mask == ppp_filter_counters[i][1])
    + return len; /* already there */
    + }
    + ppp_filter_counters[ppp_filter_counters_count][0] = ip;
    + ppp_filter_counters[ppp_filter_counters_count][1] = mask;
    + ppp_filter_counters_count++;
    + return len;
    + } else {
    + for (i = 0; i < ppp_filter_counters_count; i++) {
    + if (ip == ppp_filter_counters[i][0] && mask == ppp_filter_counters[i][1]) {
    + pr_notice("ppp_filter_counters: removed %d.%d.%d.%d/%d\n",
    + ip_byte[3], ip_byte[2], ip_byte[1], ip_byte[0], masklen);
    + for (j = i; j < ppp_filter_counters_count - 1; j++) {
    + ppp_filter_counters[j][0] = ppp_filter_counters[j+1][0];
    + ppp_filter_counters[j][1] = ppp_filter_counters[j+1][1];
    + }
    + ppp_filter_counters_count--;
    + return len;
    + }
    + }
    + }
    + }
    + return len;
    +}
    +
    +static int ppp_filter_counters_proc_show(struct seq_file *m, void *v) {
    + unsigned int i, j, mask = 0;
    +
    + if (ppp_filter_counters_count==0)
    + seq_printf(m, "no entries\n");
    + else for (i = 0; i < ppp_filter_counters_count; i++) {
    + for (j = 0; j < 32; j++){
    + if (((ppp_filter_counters[i][1] >> j) & 1) == 1) {
    + mask = 32 - j;
    + break;
    + }
    + }
    + seq_printf(m, "%d.%d.%d.%d/%d\n",
    + (ppp_filter_counters[i][0] >> 24) & 0x000000ff,
    + (ppp_filter_counters[i][0] >> 16) & 0x000000ff,
    + (ppp_filter_counters[i][0] >> 8) & 0x000000ff,
    + ppp_filter_counters[i][0] & 0x000000ff, mask);
    + }
    + return 0;
    +}
    +
    +static int ppp_filter_counters_proc_open(struct inode *inode, struct file *file) {
    + return single_open(file, ppp_filter_counters_proc_show, NULL);
    +}
    +
    +static const struct file_operations ppp_filter_counters_fops = {
    + .owner = THIS_MODULE,
    + .open = ppp_filter_counters_proc_open,
    + .read = seq_read,
    + .write = ppp_filter_counters_proc_write,
    + .llseek = seq_lseek,
    + .release = single_release,
    +};
    +
    +static bool ppp_filter_counters_allow(struct ppp* sppp, struct sk_buff *skb, bool tx){
    + struct iphdr *iph;
    + unsigned int ip;
    + int i;
    +
    + if (ppp_filter_counters_count == 0)
    + return true;
    + if (sppp == NULL || skb == NULL || PPP_PROTO(skb) != PPP_IP)
    + return true;
    +
    + iph = (struct iphdr*)skb_network_header(skb);
    + if (iph == NULL || iph->ihl < 5){
    + iph = (struct iphdr*) ((char*)skb->data+2);
    + }
    + if (iph == NULL)
    + return true;
    +
    + if (tx)
    + ip = ntohl(iph->saddr);
    + else
    + ip = ntohl(iph->daddr);
    +
    + if (ppp_filter_counters_debug)
    + netdev_printk(KERN_DEBUG, sppp->dev, "ppp_filter_counters: src=%pI4h dst=%pI4h\n", ntohl(iph->saddr), ntohl(iph->daddr));
    + for (i=0; i<ppp_filter_counters_count; i++){
    + if (!((ppp_filter_counters[i][0]&ppp_filter_counters[i][1]) ^ (ip&ppp_filter_counters[i][1]))) {
    + if (ppp_filter_counters_debug)
    + netdev_printk(KERN_DEBUG, sppp->dev, "ppp_filter_counters: not counting %pI4h\n", ip);
    + return false; /* do not count */
    + }
    + }
    + return true; /* count */
    +}
    +
    +static bool ppp_filter_counters_init(void) {
    + struct proc_dir_entry *e;
    +
    + ppp_filter_counters_count = 0;
    + ppp_filter_counters_debug = false;
    + e = proc_create(PPP_FILTER_COUNTERS_PROCNAME, 0644, NULL, &ppp_filter_counters_fops);
    + return e == NULL; /* return false on success, true on failure */
    +}
    +#endif /*CONFIG_PPP_FILTER_COUNTERS*/
    +
    /*
    * /dev/ppp device routines.
    * The /dev/ppp device is used by pppd to control the ppp unit.
    @@ -932,6 +1112,11 @@
    goto out_chrdev;
    }

    +#ifdef CONFIG_PPP_FILTER_COUNTERS
    + if (ppp_filter_counters_init())
    + pr_err( "failed to initialize ppp_filter_counters\n");
    +#endif
    +
    /* not a big deal if we fail here :-) */
    device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");

    @@ -1203,8 +1388,14 @@
    #endif /* CONFIG_PPP_FILTER */
    }

    +#ifdef CONFIG_PPP_FILTER_COUNTERS
    + if (proto != PPP_IP || ppp_filter_counters_allow(ppp, skb, true)) {
    +#endif
    ++ppp->stats64.tx_packets;
    ppp->stats64.tx_bytes += skb->len - 2;
    +#ifdef CONFIG_PPP_FILTER_COUNTERS
    + }
    +#endif

    switch (proto) {
    case PPP_IP:
    @@ -1791,8 +1982,14 @@
    break;
    }

    +#ifdef CONFIG_PPP_FILTER_COUNTERS
    + if (proto != PPP_IP || ppp_filter_counters_allow(ppp, skb, false)) {
    +#endif
    ++ppp->stats64.rx_packets;
    ppp->stats64.rx_bytes += skb->len - 2;
    +#ifdef CONFIG_PPP_FILTER_COUNTERS
    + }
    +#endif

    npi = proto_to_npindex(proto);
    if (npi < 0) {