net - IP_NODEFRAG option for IPv4 socket
authorJiri Olsa <jolsa@redhat.com>
Tue, 15 Jun 2010 01:07:31 +0000 (01:07 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 23 Jun 2010 20:16:38 +0000 (13:16 -0700)
this patch is implementing IP_NODEFRAG option for IPv4 socket.
The reason is, there's no other way to send out the packet with user
customized header of the reassembly part.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/in.h
include/net/inet_sock.h
net/ipv4/af_inet.c
net/ipv4/ip_sockglue.c
net/ipv4/netfilter/nf_defrag_ipv4.c

index 583c76f9c30fbef3a7427e5acf1e3159dfe65318..41d88a4689af0a77a000cfc88437a70d8abdc1fb 100644 (file)
@@ -85,6 +85,7 @@ struct in_addr {
 #define IP_RECVORIGDSTADDR   IP_ORIGDSTADDR
 
 #define IP_MINTTL       21
+#define IP_NODEFRAG     22
 
 /* IP_MTU_DISCOVER values */
 #define IP_PMTUDISC_DONT               0       /* Never send DF frames */
index 1653de515ceec95c8e9017edfdda532d4a851547..1989cfd7405fccfc6839f2742eb45b4b2d7f8712 100644 (file)
@@ -137,7 +137,8 @@ struct inet_sock {
                                hdrincl:1,
                                mc_loop:1,
                                transparent:1,
-                               mc_all:1;
+                               mc_all:1,
+                               nodefrag:1;
        int                     mc_index;
        __be32                  mc_addr;
        struct ip_mc_socklist   *mc_list;
index d99e7e020189144fc37da21618ee5c03f67ed203..b4c0969137cb6b790431e3ff441a768a8911b866 100644 (file)
@@ -355,6 +355,8 @@ lookup_protocol:
        inet = inet_sk(sk);
        inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
 
+       inet->nodefrag = 0;
+
        if (SOCK_RAW == sock->type) {
                inet->inet_num = protocol;
                if (IPPROTO_RAW == protocol)
index 47fff528ff39eaaf231fd22338fcff81b9e9b9da..6c40a8c46e7984843275af12bfbac9a241e8e4c6 100644 (file)
@@ -465,7 +465,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
                             (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
                             (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
                             (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
-                            (1<<IP_MINTTL))) ||
+                            (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
            optname == IP_MULTICAST_TTL ||
            optname == IP_MULTICAST_ALL ||
            optname == IP_MULTICAST_LOOP ||
@@ -588,6 +588,13 @@ static int do_ip_setsockopt(struct sock *sk, int level,
                }
                inet->hdrincl = val ? 1 : 0;
                break;
+       case IP_NODEFRAG:
+               if (sk->sk_type != SOCK_RAW) {
+                       err = -ENOPROTOOPT;
+                       break;
+               }
+               inet->nodefrag = val ? 1 : 0;
+               break;
        case IP_MTU_DISCOVER:
                if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_PROBE)
                        goto e_inval;
index cb763ae9ed9035f5be305eb33dda2e8118d671b3..eab8de32f200af74828bbf0fb3187ff578451e9b 100644 (file)
@@ -66,6 +66,11 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
                                          const struct net_device *out,
                                          int (*okfn)(struct sk_buff *))
 {
+       struct inet_sock *inet = inet_sk(skb->sk);
+
+       if (inet && inet->nodefrag)
+               return NF_ACCEPT;
+
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 #if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
        /* Previously seen (loopback)?  Ignore.  Do this before