Commit 4a19ec5800fc3bb64e2d87c4d9fdd9e636086fe0

Authored by Laszlo Attila Toth
Committed by David S. Miller
1 parent 036c2e27bc

[NET]: Introducing socket mark socket option.

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>

Showing 27 changed files with 65 additions and 0 deletions Side-by-side Diff

include/asm-alpha/socket.h
... ... @@ -60,5 +60,7 @@
60 60 #define SO_SECURITY_ENCRYPTION_TRANSPORT 20
61 61 #define SO_SECURITY_ENCRYPTION_NETWORK 21
62 62  
  63 +#define SO_MARK 36
  64 +
63 65 #endif /* _ASM_SOCKET_H */
include/asm-arm/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* _ASM_SOCKET_H */
include/asm-avr32/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* __ASM_AVR32_SOCKET_H */
include/asm-blackfin/socket.h
... ... @@ -50,5 +50,8 @@
50 50 #define SO_PASSSEC 34
51 51 #define SO_TIMESTAMPNS 35
52 52 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
  53 +
  54 +#define SO_MARK 36
  55 +
53 56 #endif /* _ASM_SOCKET_H */
include/asm-cris/socket.h
... ... @@ -54,5 +54,7 @@
54 54 #define SO_TIMESTAMPNS 35
55 55 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
56 56  
  57 +#define SO_MARK 36
  58 +
57 59 #endif /* _ASM_SOCKET_H */
include/asm-frv/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* _ASM_SOCKET_H */
include/asm-h8300/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* _ASM_SOCKET_H */
include/asm-ia64/socket.h
... ... @@ -61,5 +61,7 @@
61 61 #define SO_TIMESTAMPNS 35
62 62 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
63 63  
  64 +#define SO_MARK 36
  65 +
64 66 #endif /* _ASM_IA64_SOCKET_H */
include/asm-m32r/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* _ASM_M32R_SOCKET_H */
include/asm-m68k/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* _ASM_SOCKET_H */
include/asm-mips/socket.h
... ... @@ -73,6 +73,8 @@
73 73 #define SO_TIMESTAMPNS 35
74 74 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
75 75  
  76 +#define SO_MARK 36
  77 +
76 78 #ifdef __KERNEL__
77 79  
78 80 /** sock_type - Socket types
include/asm-parisc/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_PEERSEC 0x401d
53 53 #define SO_PASSSEC 0x401e
54 54  
  55 +#define SO_MARK 0x401f
  56 +
55 57 #endif /* _ASM_SOCKET_H */
include/asm-powerpc/socket.h
... ... @@ -59,5 +59,7 @@
59 59 #define SO_TIMESTAMPNS 35
60 60 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
61 61  
  62 +#define SO_MARK 36
  63 +
62 64 #endif /* _ASM_POWERPC_SOCKET_H */
include/asm-s390/socket.h
... ... @@ -60,5 +60,7 @@
60 60 #define SO_TIMESTAMPNS 35
61 61 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
62 62  
  63 +#define SO_MARK 36
  64 +
63 65 #endif /* _ASM_SOCKET_H */
include/asm-sh/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* __ASM_SH_SOCKET_H */
include/asm-sparc/socket.h
... ... @@ -52,6 +52,8 @@
52 52 #define SO_TIMESTAMPNS 0x0021
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 0x0022
  56 +
55 57 /* Security levels - as per NRL IPv6 - don't actually do anything */
56 58 #define SO_SECURITY_AUTHENTICATION 0x5001
57 59 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
include/asm-sparc64/socket.h
... ... @@ -57,5 +57,6 @@
57 57 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
58 58 #define SO_SECURITY_ENCRYPTION_NETWORK 0x5004
59 59  
  60 +#define SO_MARK 0x0022
60 61 #endif /* _ASM_SOCKET_H */
include/asm-v850/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* __V850_SOCKET_H__ */
include/asm-x86/socket.h
... ... @@ -52,5 +52,7 @@
52 52 #define SO_TIMESTAMPNS 35
53 53 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 54  
  55 +#define SO_MARK 36
  56 +
55 57 #endif /* _ASM_SOCKET_H */
include/asm-xtensa/socket.h
... ... @@ -63,5 +63,7 @@
63 63 #define SO_TIMESTAMPNS 35
64 64 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS
65 65  
  66 +#define SO_MARK 36
  67 +
66 68 #endif /* _XTENSA_SOCKET_H */
... ... @@ -27,6 +27,7 @@
27 27 #include <net/dst.h>
28 28 #include <net/inetpeer.h>
29 29 #include <net/flow.h>
  30 +#include <net/sock.h>
30 31 #include <linux/in_route.h>
31 32 #include <linux/rtnetlink.h>
32 33 #include <linux/route.h>
... ... @@ -149,6 +150,7 @@
149 150 int flags)
150 151 {
151 152 struct flowi fl = { .oif = oif,
  153 + .mark = sk->sk_mark,
152 154 .nl_u = { .ip4_u = { .daddr = dst,
153 155 .saddr = src,
154 156 .tos = tos } },
... ... @@ -262,6 +262,8 @@
262 262 __u32 sk_sndmsg_off;
263 263 int sk_write_pending;
264 264 void *sk_security;
  265 + __u32 sk_mark;
  266 + /* XXX 4 bytes hole on 64 bit */
265 267 void (*sk_state_change)(struct sock *sk);
266 268 void (*sk_data_ready)(struct sock *sk, int bytes);
267 269 void (*sk_write_space)(struct sock *sk);
... ... @@ -667,6 +667,13 @@
667 667 else
668 668 clear_bit(SOCK_PASSSEC, &sock->flags);
669 669 break;
  670 + case SO_MARK:
  671 + if (!capable(CAP_NET_ADMIN))
  672 + ret = -EPERM;
  673 + else {
  674 + sk->sk_mark = val;
  675 + }
  676 + break;
670 677  
671 678 /* We implement the SO_SNDLOWAT etc to
672 679 not be settable (1003.1g 5.3) */
... ... @@ -835,6 +842,10 @@
835 842  
836 843 case SO_PEERSEC:
837 844 return security_socket_getpeersec_stream(sock, optval, optlen, len);
  845 +
  846 + case SO_MARK:
  847 + v.val = sk->sk_mark;
  848 + break;
838 849  
839 850 default:
840 851 return -ENOPROTOOPT;
net/ipv4/ip_output.c
... ... @@ -168,6 +168,7 @@
168 168 }
169 169  
170 170 skb->priority = sk->sk_priority;
  171 + skb->mark = sk->sk_mark;
171 172  
172 173 /* Send it out. */
173 174 return ip_local_out(skb);
... ... @@ -385,6 +386,7 @@
385 386 (skb_shinfo(skb)->gso_segs ?: 1) - 1);
386 387  
387 388 skb->priority = sk->sk_priority;
  389 + skb->mark = sk->sk_mark;
388 390  
389 391 return ip_local_out(skb);
390 392  
... ... @@ -1286,6 +1288,7 @@
1286 1288 iph->daddr = rt->rt_dst;
1287 1289  
1288 1290 skb->priority = sk->sk_priority;
  1291 + skb->mark = sk->sk_mark;
1289 1292 skb->dst = dst_clone(&rt->u.dst);
1290 1293  
1291 1294 if (iph->protocol == IPPROTO_ICMP)
... ... @@ -352,6 +352,7 @@
352 352 skb_reserve(skb, hh_len);
353 353  
354 354 skb->priority = sk->sk_priority;
  355 + skb->mark = sk->sk_mark;
355 356 skb->dst = dst_clone(&rt->u.dst);
356 357  
357 358 skb_reset_network_header(skb);
... ... @@ -544,6 +545,7 @@
544 545  
545 546 {
546 547 struct flowi fl = { .oif = ipc.oif,
  548 + .mark = sk->sk_mark,
547 549 .nl_u = { .ip4_u =
548 550 { .daddr = daddr,
549 551 .saddr = saddr,
net/ipv6/ip6_output.c
... ... @@ -257,6 +257,7 @@
257 257 ipv6_addr_copy(&hdr->daddr, first_hop);
258 258  
259 259 skb->priority = sk->sk_priority;
  260 + skb->mark = sk->sk_mark;
260 261  
261 262 mtu = dst_mtu(dst);
262 263 if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) {
... ... @@ -1439,6 +1440,7 @@
1439 1440 ipv6_addr_copy(&hdr->daddr, final_dst);
1440 1441  
1441 1442 skb->priority = sk->sk_priority;
  1443 + skb->mark = sk->sk_mark;
1442 1444  
1443 1445 skb->dst = dst_clone(&rt->u.dst);
1444 1446 IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
... ... @@ -641,6 +641,7 @@
641 641 skb_reserve(skb, hh_len);
642 642  
643 643 skb->priority = sk->sk_priority;
  644 + skb->mark = sk->sk_mark;
644 645 skb->dst = dst_clone(&rt->u.dst);
645 646  
646 647 skb_put(skb, length);
... ... @@ -766,6 +767,8 @@
766 767 * Get and verify the address.
767 768 */
768 769 memset(&fl, 0, sizeof(fl));
  770 +
  771 + fl.mark = sk->sk_mark;
769 772  
770 773 if (sin6) {
771 774 if (addr_len < SIN6_LEN_RFC2133)