Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[IPv4] RAW: Compact the API for the kernel

The raw sockets functions are explicitly used from
inside the kernel in two places:

1. in ip_local_deliver_finish to intercept skb-s
2. in icmp_error

For this purposes many functions and even data structures,
that are naturally internal for raw protocol, are exported.

Compact the API to two functions and hide all the other
(including hash table and rwlock) inside the net/ipv4/raw.c

Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Pavel Emelyanov and committed by
David S. Miller
7bc54c90 e372c414

+56 -47
+3 -16
include/net/raw.h
··· 22 22 23 23 extern struct proto raw_prot; 24 24 25 - extern void raw_err(struct sock *, struct sk_buff *, u32 info); 25 + void raw_icmp_error(struct sk_buff *, int, u32); 26 + int raw_local_deliver(struct sk_buff *, int); 27 + 26 28 extern int raw_rcv(struct sock *, struct sk_buff *); 27 - 28 - /* Note: v4 ICMP wants to get at this stuff, if you change the 29 - * hashing mechanism, make sure you update icmp.c as well. 30 - */ 31 - #define RAWV4_HTABLE_SIZE MAX_INET_PROTOS 32 - extern struct hlist_head raw_v4_htable[RAWV4_HTABLE_SIZE]; 33 - 34 - extern rwlock_t raw_v4_lock; 35 - 36 - 37 - extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num, 38 - __be32 raddr, __be32 laddr, 39 - int dif); 40 - 41 - extern int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash); 42 29 43 30 #ifdef CONFIG_PROC_FS 44 31 extern int raw_proc_init(void);
+1 -14
net/ipv4/icmp.c
··· 603 603 struct icmphdr *icmph; 604 604 int hash, protocol; 605 605 struct net_protocol *ipprot; 606 - struct sock *raw_sk; 607 606 u32 info = 0; 608 607 609 608 /* ··· 696 697 /* 697 698 * Deliver ICMP message to raw sockets. Pretty useless feature? 698 699 */ 700 + raw_icmp_error(skb, protocol, info); 699 701 700 - /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */ 701 702 hash = protocol & (MAX_INET_PROTOS - 1); 702 - read_lock(&raw_v4_lock); 703 - if ((raw_sk = sk_head(&raw_v4_htable[hash])) != NULL) { 704 - while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr, 705 - iph->saddr, 706 - skb->dev->ifindex)) != NULL) { 707 - raw_err(raw_sk, skb, info); 708 - raw_sk = sk_next(raw_sk); 709 - iph = (struct iphdr *)skb->data; 710 - } 711 - } 712 - read_unlock(&raw_v4_lock); 713 - 714 703 rcu_read_lock(); 715 704 ipprot = rcu_dereference(inet_protos[hash]); 716 705 if (ipprot && ipprot->err_handler)
+4 -12
net/ipv4/ip_input.c
··· 204 204 205 205 rcu_read_lock(); 206 206 { 207 - /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */ 208 207 int protocol = ip_hdr(skb)->protocol; 209 - int hash; 210 - struct sock *raw_sk; 208 + int hash, raw; 211 209 struct net_protocol *ipprot; 212 210 213 211 resubmit: 212 + raw = raw_local_deliver(skb, protocol); 213 + 214 214 hash = protocol & (MAX_INET_PROTOS - 1); 215 - raw_sk = sk_head(&raw_v4_htable[hash]); 216 - 217 - /* If there maybe a raw socket we must check - if not we 218 - * don't care less 219 - */ 220 - if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash)) 221 - raw_sk = NULL; 222 - 223 215 if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) { 224 216 int ret; 225 217 ··· 229 237 } 230 238 IP_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); 231 239 } else { 232 - if (!raw_sk) { 240 + if (!raw) { 233 241 if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { 234 242 IP_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS); 235 243 icmp_send(skb, ICMP_DEST_UNREACH,
+48 -5
net/ipv4/raw.c
··· 80 80 #include <linux/netfilter.h> 81 81 #include <linux/netfilter_ipv4.h> 82 82 83 - struct hlist_head raw_v4_htable[RAWV4_HTABLE_SIZE]; 84 - DEFINE_RWLOCK(raw_v4_lock); 83 + #define RAWV4_HTABLE_SIZE MAX_INET_PROTOS 84 + 85 + static struct hlist_head raw_v4_htable[RAWV4_HTABLE_SIZE]; 86 + static DEFINE_RWLOCK(raw_v4_lock); 85 87 86 88 static void raw_v4_hash(struct sock *sk) 87 89 { ··· 104 102 write_unlock_bh(&raw_v4_lock); 105 103 } 106 104 107 - struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num, 105 + static struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num, 108 106 __be32 raddr, __be32 laddr, 109 107 int dif) 110 108 { ··· 152 150 * RFC 1122: SHOULD pass TOS value up to the transport layer. 153 151 * -> It does. And not only TOS, but all IP header. 154 152 */ 155 - int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) 153 + static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) 156 154 { 157 155 struct sock *sk; 158 156 struct hlist_head *head; ··· 184 182 return delivered; 185 183 } 186 184 187 - void raw_err (struct sock *sk, struct sk_buff *skb, u32 info) 185 + int raw_local_deliver(struct sk_buff *skb, int protocol) 186 + { 187 + int hash; 188 + struct sock *raw_sk; 189 + 190 + hash = protocol & (RAWV4_HTABLE_SIZE - 1); 191 + raw_sk = sk_head(&raw_v4_htable[hash]); 192 + 193 + /* If there maybe a raw socket we must check - if not we 194 + * don't care less 195 + */ 196 + if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash)) 197 + raw_sk = NULL; 198 + 199 + return raw_sk != NULL; 200 + 201 + } 202 + 203 + static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) 188 204 { 189 205 struct inet_sock *inet = inet_sk(sk); 190 206 const int type = icmp_hdr(skb)->type; ··· 254 234 sk->sk_err = err; 255 235 sk->sk_error_report(sk); 256 236 } 237 + } 238 + 239 + void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) 240 + { 241 + int hash; 242 + struct sock *raw_sk; 243 + struct iphdr *iph; 244 + 245 + hash = protocol & (RAWV4_HTABLE_SIZE - 1); 246 + 247 + read_lock(&raw_v4_lock); 248 + raw_sk = sk_head(&raw_v4_htable[hash]); 249 + if (raw_sk != NULL) { 250 + iph = (struct iphdr *)skb->data; 251 + while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr, 252 + iph->saddr, 253 + skb->dev->ifindex)) != NULL) { 254 + raw_err(raw_sk, skb, info); 255 + raw_sk = sk_next(raw_sk); 256 + iph = (struct iphdr *)skb->data; 257 + } 258 + } 259 + read_unlock(&raw_v4_lock); 257 260 } 258 261 259 262 static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb)