*/
/* Define this to get the SOCK_DBG debugging facility. */
-//#define SOCK_DEBUGGING
+#define SOCK_DEBUGGING
#ifdef SOCK_DEBUGGING
#define SOCK_DEBUG(sk, msg...) do { if ((sk) && sock_flag((sk), SOCK_DBG)) \
printk(KERN_DEBUG msg); } while (0)
* @sk_timer: sock cleanup timer
* @sk_stamp: time stamp of last packet received
* @sk_socket: Identd and reporting IO signals
- * @sk_user_data: RPC and Tux layer private data
+ * @sk_user_data: RPC layer private data
* @sk_sndmsg_page: cached page for sendmsg
* @sk_sndmsg_off: cached offset for sendmsg
* @sk_send_head: front of stuff to transmit
* @sk_data_ready: callback to indicate there is data to be processed
* @sk_write_space: callback to indicate there is bf sending space available
* @sk_error_report: callback to indicate errors (e.g. %MSG_ERRQUEUE)
- * @sk_create_child - callback to get new socket events
* @sk_backlog_rcv: callback to process the backlog
* @sk_destruct: called at sock freeing time, i.e. when all refcnt == 0
*/
gfp_t sk_allocation;
int sk_sndbuf;
int sk_route_caps;
- int sk_rcvlowat;
unsigned long sk_flags;
unsigned long sk_lingertime;
/*
unsigned short sk_max_ack_backlog;
__u32 sk_priority;
struct ucred sk_peercred;
+ int sk_rcvlowat;
long sk_rcvtimeo;
long sk_sndtimeo;
struct sk_filter *sk_filter;
void (*sk_error_report)(struct sock *sk);
int (*sk_backlog_rcv)(struct sock *sk,
struct sk_buff *skb);
- void (*sk_create_child)(struct sock *sk, struct sock *newsk);
void (*sk_destruct)(struct sock *sk);
};
static inline int sk_hashed(const struct sock *sk)
{
- return !sk_unhashed(sk);
+ return sk->sk_node.pprev != NULL;
}
static __inline__ void sk_node_init(struct hlist_node *node)
static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
{
- skb_truesize_check(skb);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
sk->sk_wmem_queued -= skb->truesize;
sk->sk_forward_alloc += skb->truesize;
int (*getsockopt)(struct sock *sk, int level,
int optname, char __user *optval,
int __user *option);
- int (*compat_setsockopt)(struct sock *sk,
- int level,
- int optname, char __user *optval,
- int optlen);
- int (*compat_getsockopt)(struct sock *sk,
- int level,
- int optname, char __user *optval,
- int __user *option);
int (*sendmsg)(struct kiocb *iocb, struct sock *sk,
struct msghdr *msg, size_t len);
int (*recvmsg)(struct kiocb *iocb, struct sock *sk,
gfp_t priority,
struct proto *prot, int zero_it);
extern void sk_free(struct sock *sk);
-extern struct sock *sk_clone(struct sock *sk,
+extern struct sock *sk_clone(const struct sock *sk,
const gfp_t priority);
extern struct sk_buff *sock_wmalloc(struct sock *sk,
struct msghdr *msg, size_t size, int flags);
extern int sock_common_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen);
-extern int compat_sock_common_getsockopt(struct socket *sock, int level,
- int optname, char __user *optval, int __user *optlen);
-extern int compat_sock_common_setsockopt(struct socket *sock, int level,
- int optname, char __user *optval, int optlen);
extern void sk_common_release(struct sock *sk);
sk_free(sk);
}
-extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb);
+static inline int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = NET_RX_SUCCESS;
+
+ if (sk_filter(sk, skb, 0))
+ goto discard_and_relse;
+
+ skb->dev = NULL;
+
+ bh_lock_sock(sk);
+ if (!sock_owned_by_user(sk))
+ rc = sk->sk_backlog_rcv(sk, skb);
+ else
+ sk_add_backlog(sk, skb);
+ bh_unlock_sock(sk);
+out:
+ sock_put(sk);
+ return rc;
+discard_and_relse:
+ kfree_skb(skb);
+ goto out;
+}
/* Detach socket from process context.
* Announce socket dead, detach it from wait queue and inode.
write_unlock(&sk->sk_dst_lock);
}
-extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
+static inline struct dst_entry *
+__sk_dst_check(struct sock *sk, u32 cookie)
+{
+ struct dst_entry *dst = sk->sk_dst_cache;
+
+ if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+ sk->sk_dst_cache = NULL;
+ dst_release(dst);
+ return NULL;
+ }
+
+ return dst;
+}
-extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
+static inline struct dst_entry *
+sk_dst_check(struct sock *sk, u32 cookie)
+{
+ struct dst_entry *dst = sk_dst_get(sk);
+
+ if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+ sk_dst_reset(sk);
+ dst_release(dst);
+ return NULL;
+ }
+
+ return dst;
+}
static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
__sk_dst_set(sk, dst);
sk->sk_route_caps = dst->dev->features;
- if (sk->sk_route_caps & NETIF_F_GSO)
- sk->sk_route_caps |= NETIF_F_TSO;
if (sk->sk_route_caps & NETIF_F_TSO) {
if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
sk->sk_route_caps &= ~NETIF_F_TSO;
- else
- sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
}
}
extern void sk_stop_timer(struct sock *sk, struct timer_list* timer);
+#if defined(CONFIG_VNET) || defined(CONFIG_VNET_MODULE)
extern int vnet_active;
+#endif
+
+static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+ int err = 0;
+ int skb_len;
+
+#if defined(CONFIG_VNET) || defined(CONFIG_VNET_MODULE)
+ /* Silently drop if VNET is active (if INET bind() has been
+ * overridden) and the context is not entitled to read the
+ * packet.
+ */
+ if (vnet_active &&
+ (int) sk->sk_xid > 0 && sk->sk_xid != skb->xid) {
+ err = -EPERM;
+ goto out;
+ }
+#endif
+
+ /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
+ number of warnings when compiling with -W --ANK
+ */
+ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+ (unsigned)sk->sk_rcvbuf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* It would be deadlock, if sock_queue_rcv_skb is used
+ with socket lock! We assume that users of this
+ function are lock free.
+ */
+ err = sk_filter(sk, skb, 1);
+ if (err)
+ goto out;
+
+ skb->dev = NULL;
+ skb_set_owner_r(skb, sk);
-extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
+ /* Cache the SKB length before we tack it onto the receive
+ * queue. Once it is added it no longer belongs to us and
+ * may be freed by other threads of control pulling packets
+ * from the queue.
+ */
+ skb_len = skb->len;
+
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk, skb_len);
+out:
+ return err;
+}
static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
{