LCOV - code coverage report
Current view: top level - home/snorch/criu - netfilter.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 32 43 74.4 %
Date: 2014-04-22 Functions: 4 5 80.0 %
Branches: 15 23 65.2 %

           Branch data     Line data    Source code
       1                 :            : #include <sys/socket.h>
       2                 :            : #include <arpa/inet.h>
       3                 :            : #include <unistd.h>
       4                 :            : #include <string.h>
       5                 :            : #include <wait.h>
       6                 :            : #include <stdlib.h>
       7                 :            : 
       8                 :            : #include "asm/types.h"
       9                 :            : #include "util.h"
      10                 :            : #include "list.h"
      11                 :            : #include "files.h"
      12                 :            : #include "netfilter.h"
      13                 :            : #include "sockets.h"
      14                 :            : #include "sk-inet.h"
      15                 :            : 
      16                 :            : static char buf[512];
      17                 :            : 
      18                 :            : /*
      19                 :            :  * Need to configure simple netfilter rules for blocking connections
      20                 :            :  * ANy brave soul to write it using xtables-devel?
      21                 :            :  */
      22                 :            : 
      23                 :            : static const char *nf_conn_cmd = "%s -t filter %s %s --protocol tcp "
      24                 :            :         "--source %s --sport %d --destination %s --dport %d -j DROP";
      25                 :            : 
      26                 :            : static char iptable_cmd_ipv4[] = "iptables";
      27                 :            : static char iptable_cmd_ipv6[] = "ip6tables";
      28                 :            : 
      29                 :         96 : static int nf_connection_switch_raw(int family, u32 *src_addr, u16 src_port,
      30                 :            :                                                 u32 *dst_addr, u16 dst_port,
      31                 :            :                                                 bool input, bool lock)
      32                 :            : {
      33                 :            :         char sip[INET_ADDR_LEN], dip[INET_ADDR_LEN];
      34                 :            :         char *cmd;
      35                 :         96 :         char *argv[4] = { "sh", "-c", buf, NULL };
      36                 :            :         int ret;
      37                 :            : 
      38      [ +  -  + ]:         96 :         switch (family) {
      39                 :            :         case AF_INET:
      40                 :            :                 cmd = iptable_cmd_ipv4;
      41                 :            :                 break;
      42                 :            :         case AF_INET6:
      43                 :            :                 cmd = iptable_cmd_ipv6;
      44                 :         32 :                 break;
      45                 :            :         default:
      46                 :          0 :                 pr_err("Unknown socket family %d\n", family);
      47                 :          0 :                 return -1;
      48                 :            :         };
      49                 :            : 
      50   [ +  -  -  + ]:        192 :         if (!inet_ntop(family, (void *)src_addr, sip, INET_ADDR_LEN) ||
      51                 :         96 :                         !inet_ntop(family, (void *)dst_addr, dip, INET_ADDR_LEN)) {
      52                 :          0 :                 pr_perror("nf: Can't translate ip addr");
      53                 :          0 :                 return -1;
      54                 :            :         }
      55                 :            : 
      56 [ +  + ][ +  + ]:         96 :         snprintf(buf, sizeof(buf), nf_conn_cmd, cmd,
      57                 :            :                         lock ? "-A" : "-D",
      58                 :            :                         input ? "INPUT" : "OUTPUT",
      59                 :            :                         dip, (int)dst_port, sip, (int)src_port);
      60                 :            : 
      61                 :         96 :         pr_debug("\tRunning iptables [%s]\n", buf);
      62                 :            : 
      63                 :            :         /*
      64                 :            :          * cr_system is used here, because it blocks SIGCHLD before waiting
      65                 :            :          * a child and the child can't be waited from SIGCHLD handler.
      66                 :            :          */
      67                 :         96 :         ret = cr_system(-1, -1, -1, "sh", argv);
      68 [ +  - ][ +  - ]:         96 :         if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret)) {
                 [ -  + ]
      69                 :          0 :                 pr_perror("Iptables configuration failed");
      70                 :          0 :                 return -1;
      71                 :            :         }
      72                 :            : 
      73         [ +  + ]:         96 :         pr_info("%s %s:%d - %s:%d connection\n", lock ? "Locked" : "Unlocked",
      74                 :            :                         sip, (int)src_port, dip, (int)dst_port);
      75                 :         96 :         return 0;
      76                 :            : }
      77                 :            : 
      78                 :         24 : static int nf_connection_switch(struct inet_sk_desc *sk, bool lock)
      79                 :            : {
      80                 :            :         int ret = 0;
      81                 :            : 
      82                 :         24 :         ret = nf_connection_switch_raw(sk->sd.family,
      83                 :         48 :                         sk->src_addr, sk->src_port,
      84                 :         48 :                         sk->dst_addr, sk->dst_port, true, lock);
      85         [ +  - ]:         24 :         if (ret)
      86                 :            :                 return -1;
      87                 :            : 
      88                 :         24 :         ret = nf_connection_switch_raw(sk->sd.family,
      89                 :         24 :                         sk->dst_addr, sk->dst_port,
      90                 :         24 :                         sk->src_addr, sk->src_port, false, lock);
      91         [ -  + ]:         24 :         if (ret) /* rollback */
      92                 :          0 :                 nf_connection_switch_raw(sk->sd.family,
      93                 :          0 :                         sk->src_addr, sk->src_port,
      94                 :          0 :                         sk->dst_addr, sk->dst_port, true, !lock);
      95                 :         24 :         return ret;
      96                 :            : }
      97                 :            : 
      98                 :         24 : int nf_lock_connection(struct inet_sk_desc *sk)
      99                 :            : {
     100                 :         24 :         return nf_connection_switch(sk, true);
     101                 :            : }
     102                 :            : 
     103                 :          0 : int nf_unlock_connection(struct inet_sk_desc *sk)
     104                 :            : {
     105                 :          0 :         return nf_connection_switch(sk, false);
     106                 :            : }
     107                 :            : 
     108                 :         24 : int nf_unlock_connection_info(struct inet_sk_info *si)
     109                 :            : {
     110                 :            :         int ret = 0;
     111                 :            : 
     112                 :         24 :         ret |= nf_connection_switch_raw(si->ie->family,
     113                 :         48 :                         si->ie->src_addr, si->ie->src_port,
     114                 :         48 :                         si->ie->dst_addr, si->ie->dst_port, true, false);
     115                 :         24 :         ret |= nf_connection_switch_raw(si->ie->family,
     116                 :         48 :                         si->ie->dst_addr, si->ie->dst_port,
     117                 :         48 :                         si->ie->src_addr, si->ie->src_port, false, false);
     118                 :            :         /*
     119                 :            :          * rollback nothing in case of any error,
     120                 :            :          * because nobody checks errors of this function
     121                 :            :          */
     122                 :            : 
     123                 :         24 :         return ret;
     124                 :            : }

Generated by: LCOV version 1.9