From: Laszlo Attila Toth Date: Thu, 31 Jan 2008 03:08:16 +0000 (-0800) Subject: [NET]: Introducing socket mark socket option. X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=4a19ec5800fc3bb64e2d87c4d9fdd9e636086fe0;p=linux.git [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 Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h index 1fede7f928600..08c9793199290 100644 --- a/include/asm-alpha/socket.h +++ b/include/asm-alpha/socket.h @@ -60,4 +60,6 @@ #define SO_SECURITY_ENCRYPTION_TRANSPORT 20 #define SO_SECURITY_ENCRYPTION_NETWORK 21 +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-arm/socket.h b/include/asm-arm/socket.h index 65a1a64bf9340..6817be9573a6b 100644 --- a/include/asm-arm/socket.h +++ b/include/asm-arm/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-avr32/socket.h b/include/asm-avr32/socket.h index a0d0507a50349..35863f260929a 100644 --- a/include/asm-avr32/socket.h +++ b/include/asm-avr32/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* __ASM_AVR32_SOCKET_H */ diff --git a/include/asm-blackfin/socket.h b/include/asm-blackfin/socket.h index 5213c96521860..2ca702e44d475 100644 --- a/include/asm-blackfin/socket.h +++ b/include/asm-blackfin/socket.h @@ -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 */ diff --git a/include/asm-cris/socket.h b/include/asm-cris/socket.h index 5b18dfdf1748f..9df0ca82f5ded 100644 --- a/include/asm-cris/socket.h +++ b/include/asm-cris/socket.h @@ -54,6 +54,8 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-frv/socket.h b/include/asm-frv/socket.h index a823befd11dd8..e51ca67b9356c 100644 --- a/include/asm-frv/socket.h +++ b/include/asm-frv/socket.h @@ -52,5 +52,7 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-h8300/socket.h b/include/asm-h8300/socket.h index 39911d8c96840..da2520dbf2547 100644 --- a/include/asm-h8300/socket.h +++ b/include/asm-h8300/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h index 9e42ce43cfbea..d5ef0aa3e312e 100644 --- a/include/asm-ia64/socket.h +++ b/include/asm-ia64/socket.h @@ -61,4 +61,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_IA64_SOCKET_H */ diff --git a/include/asm-m32r/socket.h b/include/asm-m32r/socket.h index 793d5d30c8505..9a0e200122249 100644 --- a/include/asm-m32r/socket.h +++ b/include/asm-m32r/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_M32R_SOCKET_H */ diff --git a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h index 6d21b90863ad1..dbc64e92c41ac 100644 --- a/include/asm-m68k/socket.h +++ b/include/asm-m68k/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h index 95945689b1c66..63f60254d3087 100644 --- a/include/asm-mips/socket.h +++ b/include/asm-mips/socket.h @@ -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 diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h index 99e868f6a8f52..69a7a0d30b025 100644 --- a/include/asm-parisc/socket.h +++ b/include/asm-parisc/socket.h @@ -52,4 +52,6 @@ #define SO_PEERSEC 0x401d #define SO_PASSSEC 0x401e +#define SO_MARK 0x401f + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-powerpc/socket.h b/include/asm-powerpc/socket.h index 403e9fde2eb52..f5a4e168e498b 100644 --- a/include/asm-powerpc/socket.h +++ b/include/asm-powerpc/socket.h @@ -59,4 +59,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/include/asm-s390/socket.h b/include/asm-s390/socket.h index 1161ebe3dec95..c786ab623b2d2 100644 --- a/include/asm-s390/socket.h +++ b/include/asm-s390/socket.h @@ -60,4 +60,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-sh/socket.h b/include/asm-sh/socket.h index c48d6fc9da386..6d4bf6512959e 100644 --- a/include/asm-sh/socket.h +++ b/include/asm-sh/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* __ASM_SH_SOCKET_H */ diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h index 7c1423997cf0d..2e2bd0b7c8e3e 100644 --- a/include/asm-sparc/socket.h +++ b/include/asm-sparc/socket.h @@ -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 diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h index 986441dcb8f03..44a625af6e317 100644 --- a/include/asm-sparc64/socket.h +++ b/include/asm-sparc64/socket.h @@ -57,4 +57,5 @@ #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 #define SO_SECURITY_ENCRYPTION_NETWORK 0x5004 +#define SO_MARK 0x0022 #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-v850/socket.h b/include/asm-v850/socket.h index a4c2493b025fe..e199a2bf12aa6 100644 --- a/include/asm-v850/socket.h +++ b/include/asm-v850/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* __V850_SOCKET_H__ */ diff --git a/include/asm-x86/socket.h b/include/asm-x86/socket.h index 99ca648b94c54..80af9c4ccad7f 100644 --- a/include/asm-x86/socket.h +++ b/include/asm-x86/socket.h @@ -52,4 +52,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-xtensa/socket.h b/include/asm-xtensa/socket.h index 1f5aeacb9da27..6100682b1da22 100644 --- a/include/asm-xtensa/socket.h +++ b/include/asm-xtensa/socket.h @@ -63,4 +63,6 @@ #define SO_TIMESTAMPNS 35 #define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 + #endif /* _XTENSA_SOCKET_H */ diff --git a/include/net/route.h b/include/net/route.h index 4eabf008413bf..fcc6d5b35863d 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -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 } }, diff --git a/include/net/sock.h b/include/net/sock.h index 902324488d0f7..e3fb4c047f4c9 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -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); diff --git a/net/core/sock.c b/net/core/sock.c index 1c4b1cd16d654..433715fb141a5 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -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; } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 6e4d5f493bf9b..341779e685d91 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -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) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 85c08696abbe4..f863c3dc5421e 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -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, diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index cfe9e707883c8..9ac6ca2521c32 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -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); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4d880551fe6ab..d61c63dedbf6b 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -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;