[NET]: Introducing socket mark socket option.
authorLaszlo Attila Toth <panther@balabit.hu>
Thu, 31 Jan 2008 03:08:16 +0000 (19:08 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 Feb 2008 03:27:19 +0000 (19:27 -0800)
A userspace program may wish to set the mark for each packets its send
without using the netfilter MARK target. Changing the mark can be used
for mark based routing without netfilter or for packet filtering.

It requires CAP_NET_ADMIN capability.

Signed-off-by: Laszlo Attila Toth <panther@balabit.hu>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
27 files changed:
include/asm-alpha/socket.h
include/asm-arm/socket.h
include/asm-avr32/socket.h
include/asm-blackfin/socket.h
include/asm-cris/socket.h
include/asm-frv/socket.h
include/asm-h8300/socket.h
include/asm-ia64/socket.h
include/asm-m32r/socket.h
include/asm-m68k/socket.h
include/asm-mips/socket.h
include/asm-parisc/socket.h
include/asm-powerpc/socket.h
include/asm-s390/socket.h
include/asm-sh/socket.h
include/asm-sparc/socket.h
include/asm-sparc64/socket.h
include/asm-v850/socket.h
include/asm-x86/socket.h
include/asm-xtensa/socket.h
include/net/route.h
include/net/sock.h
net/core/sock.c
net/ipv4/ip_output.c
net/ipv4/raw.c
net/ipv6/ip6_output.c
net/ipv6/raw.c

index 1fede7f928600bd5e4b82ddbfe04c615c8f8b2f8..08c9793199290fefc36f027da65f7e7e50f9cd43 100644 (file)
@@ -60,4 +60,6 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       20
 #define SO_SECURITY_ENCRYPTION_NETWORK         21
 
+#define SO_MARK                        36
+
 #endif /* _ASM_SOCKET_H */
index 65a1a64bf9340b2b8ec8d4321d26c1deb968739a..6817be9573a6bf65d29ef5092a4a869017cf87bc 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_SOCKET_H */
index a0d0507a5034969b70bbc1139631ef5f4cdc077d..35863f260929abe002d57f154c3d5749b2ce1d69 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* __ASM_AVR32_SOCKET_H */
index 5213c96521860dc83b3ab8755f971ca2ac5c6887..2ca702e44d4759420051ed73dc9c3662eb2fb5c4 100644 (file)
@@ -50,4 +50,7 @@
 #define SO_PASSSEC             34
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
+
+#define SO_MARK                        36
+
 #endif                         /* _ASM_SOCKET_H */
index 5b18dfdf1748f2c6538ab3ca2c65d7ef3468e342..9df0ca82f5dedf90437954406dc201e1d073f898 100644 (file)
@@ -54,6 +54,8 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_SOCKET_H */
 
 
index a823befd11dd8f8ce35c0d3080717032d4c16d87..e51ca67b9356c5dfac236509c2ea00387a3ee911 100644 (file)
@@ -52,5 +52,7 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_SOCKET_H */
 
index 39911d8c968406c5040dab05d8c8d5b792d09bec..da2520dbf2547e2643af27749b178e7e5a4dd0eb 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_SOCKET_H */
index 9e42ce43cfbeaf92007e07119af6d82c16df5bae..d5ef0aa3e312e82630c0f7d636f6d0c9d2156b95 100644 (file)
@@ -61,4 +61,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_IA64_SOCKET_H */
index 793d5d30c8505f03ddb1c0e8801c771177f7e82e..9a0e200122249e5cae09d90d73b01d820dbe9e83 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_M32R_SOCKET_H */
index 6d21b90863ad1220d8f614e7b071f7bbc62d8f89..dbc64e92c41ac572bd80b99790f80977ed5e8c75 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_SOCKET_H */
index 95945689b1c669193b20765a1d202bebecca8b1a..63f60254d308741efde979586ccdd9456ac47811 100644 (file)
@@ -73,6 +73,8 @@ To add: #define SO_REUSEPORT 0x0200   /* Allow local address and port reuse.  */
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #ifdef __KERNEL__
 
 /** sock_type - Socket types
index 99e868f6a8f52fa5e13082c62306a61c53e96186..69a7a0d30b025335f927979f1eb14e7750d3c09a 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_PEERSEC             0x401d
 #define SO_PASSSEC             0x401e
 
+#define SO_MARK                        0x401f
+
 #endif /* _ASM_SOCKET_H */
index 403e9fde2eb52eea67537b823bfe9f33925a6042..f5a4e168e498b6641c3c1ea3b0afac640a233015 100644 (file)
@@ -59,4 +59,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_POWERPC_SOCKET_H */
index 1161ebe3dec9530cc0ac416722ad6c15a79de8e5..c786ab623b2d2d0f3f63aedfa5873248f40b156d 100644 (file)
@@ -60,4 +60,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_SOCKET_H */
index c48d6fc9da3866da5fc5fa3e70d5ec76f654801b..6d4bf6512959ef0a8b2e610e4fd2aeb99c88e5bf 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* __ASM_SH_SOCKET_H */
index 7c1423997cf0d41bbd0f6830e8e5993fefaec360..2e2bd0b7c8e3e34616c6621b8e7dbd2cc7683567 100644 (file)
@@ -52,6 +52,8 @@
 #define SO_TIMESTAMPNS         0x0021
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        0x0022
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
index 986441dcb8f03ba39eab3e3a972ca0e5159b7bbf..44a625af6e317e91758494fd906a3ef1597cdc79 100644 (file)
@@ -57,4 +57,5 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK         0x5004
 
+#define SO_MARK                        0x0022
 #endif /* _ASM_SOCKET_H */
index a4c2493b025feffb3ddb596e4a0072c28b88eb89..e199a2bf12aa62d80e77ab2ccd02486a59269a29 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* __V850_SOCKET_H__ */
index 99ca648b94c54122057342ec4bcef093b0d0fbe6..80af9c4ccad7f05cd09db4d0d212ec2a0753ed04 100644 (file)
@@ -52,4 +52,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _ASM_SOCKET_H */
index 1f5aeacb9da27ead7b2623a74f7a557717bfc2c0..6100682b1da22248debf67ccf0cfca02a524180f 100644 (file)
@@ -63,4 +63,6 @@
 #define SO_TIMESTAMPNS         35
 #define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
 
+#define SO_MARK                        36
+
 #endif /* _XTENSA_SOCKET_H */
index 4eabf008413bfb18390fd552e88a49f4fcf44e28..fcc6d5b35863d6d966620c3fd9d32d61906cdf14 100644 (file)
@@ -27,6 +27,7 @@
 #include <net/dst.h>
 #include <net/inetpeer.h>
 #include <net/flow.h>
+#include <net/sock.h>
 #include <linux/in_route.h>
 #include <linux/rtnetlink.h>
 #include <linux/route.h>
@@ -149,6 +150,7 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
                                   int flags)
 {
        struct flowi fl = { .oif = oif,
+                           .mark = sk->sk_mark,
                            .nl_u = { .ip4_u = { .daddr = dst,
                                                 .saddr = src,
                                                 .tos   = tos } },
index 902324488d0f7d2fb9a485258f59efa827344b0f..e3fb4c047f4c99b1bdb73471010916243e733bbf 100644 (file)
@@ -262,6 +262,8 @@ struct sock {
        __u32                   sk_sndmsg_off;
        int                     sk_write_pending;
        void                    *sk_security;
+       __u32                   sk_mark;
+       /* XXX 4 bytes hole on 64 bit */
        void                    (*sk_state_change)(struct sock *sk);
        void                    (*sk_data_ready)(struct sock *sk, int bytes);
        void                    (*sk_write_space)(struct sock *sk);
index 1c4b1cd16d654f1a6737a6bfed3ca6d445f3e8c4..433715fb141a5e0dd6eb092568f63c20c8a2fa86 100644 (file)
@@ -667,6 +667,13 @@ set_rcvbuf:
                else
                        clear_bit(SOCK_PASSSEC, &sock->flags);
                break;
+       case SO_MARK:
+               if (!capable(CAP_NET_ADMIN))
+                       ret = -EPERM;
+               else {
+                       sk->sk_mark = val;
+               }
+               break;
 
                /* We implement the SO_SNDLOWAT etc to
                   not be settable (1003.1g 5.3) */
@@ -836,6 +843,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
        case SO_PEERSEC:
                return security_socket_getpeersec_stream(sock, optval, optlen, len);
 
+       case SO_MARK:
+               v.val = sk->sk_mark;
+               break;
+
        default:
                return -ENOPROTOOPT;
        }
index 6e4d5f493bf9bf881f65bdaba2bd58efaedb7aaf..341779e685d913d41ac14ae59a141ab32dca847f 100644 (file)
@@ -168,6 +168,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
        }
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
 
        /* Send it out. */
        return ip_local_out(skb);
@@ -385,6 +386,7 @@ packet_routed:
                             (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
 
        return ip_local_out(skb);
 
@@ -1286,6 +1288,7 @@ int ip_push_pending_frames(struct sock *sk)
        iph->daddr = rt->rt_dst;
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
        skb->dst = dst_clone(&rt->u.dst);
 
        if (iph->protocol == IPPROTO_ICMP)
index 85c08696abbe40b4a38de040fe59788a5ff4138e..f863c3dc5421ead4f0573c53e0fc602e9b9ea5a8 100644 (file)
@@ -352,6 +352,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
        skb_reserve(skb, hh_len);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
        skb->dst = dst_clone(&rt->u.dst);
 
        skb_reset_network_header(skb);
@@ -544,6 +545,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        {
                struct flowi fl = { .oif = ipc.oif,
+                                   .mark = sk->sk_mark,
                                    .nl_u = { .ip4_u =
                                              { .daddr = daddr,
                                                .saddr = saddr,
index cfe9e707883c84a2f08a85c72adf12d091a2f95b..9ac6ca2521c32fba05dd4c99e9f8e68bbf762c32 100644 (file)
@@ -257,6 +257,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
        ipv6_addr_copy(&hdr->daddr, first_hop);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
 
        mtu = dst_mtu(dst);
        if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) {
@@ -1439,6 +1440,7 @@ int ip6_push_pending_frames(struct sock *sk)
        ipv6_addr_copy(&hdr->daddr, final_dst);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
 
        skb->dst = dst_clone(&rt->u.dst);
        IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
index 4d880551fe6ab327260a09401d2a5a4f3c9e7315..d61c63dedbf6b8ef9633d87ce6df70c41b8f9118 100644 (file)
@@ -641,6 +641,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
        skb_reserve(skb, hh_len);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
        skb->dst = dst_clone(&rt->u.dst);
 
        skb_put(skb, length);
@@ -767,6 +768,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
         */
        memset(&fl, 0, sizeof(fl));
 
+       fl.mark = sk->sk_mark;
+
        if (sin6) {
                if (addr_len < SIN6_LEN_RFC2133)
                        return -EINVAL;