net/atm/pvc.c

Source file repositories/reference/linux-study-clean/net/atm/pvc.c

File Facts

System
Linux kernel
Corpus path
net/atm/pvc.c
Extension
.c
Size
3794 bytes
Lines
163
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

#include <linux/net.h>		/* struct socket, struct proto_ops */
#include <linux/atm.h>		/* ATM stuff */
#include <linux/atmdev.h>	/* ATM devices */
#include <linux/errno.h>	/* error codes */
#include <linux/kernel.h>	/* printk */
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/bitops.h>
#include <linux/export.h>
#include <net/sock.h>		/* for sock_no_* */

#include "resources.h"		/* devs and vccs */
#include "common.h"		/* common for PVCs and SVCs */


static int pvc_shutdown(struct socket *sock, int how)
{
	return 0;
}

static int pvc_bind(struct socket *sock, struct sockaddr_unsized *sockaddr,
		    int sockaddr_len)
{
	struct sock *sk = sock->sk;
	struct sockaddr_atmpvc *addr;
	struct atm_vcc *vcc;
	int error;

	if (sockaddr_len != sizeof(struct sockaddr_atmpvc))
		return -EINVAL;
	addr = (struct sockaddr_atmpvc *)sockaddr;
	if (addr->sap_family != AF_ATMPVC)
		return -EAFNOSUPPORT;
	lock_sock(sk);
	vcc = ATM_SD(sock);
	if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
		error = -EBADFD;
		goto out;
	}
	if (test_bit(ATM_VF_PARTIAL, &vcc->flags)) {
		if (vcc->vpi != ATM_VPI_UNSPEC)
			addr->sap_addr.vpi = vcc->vpi;
		if (vcc->vci != ATM_VCI_UNSPEC)
			addr->sap_addr.vci = vcc->vci;
	}
	error = vcc_connect(sock, addr->sap_addr.itf, addr->sap_addr.vpi,
			    addr->sap_addr.vci);
out:
	release_sock(sk);
	return error;
}

static int pvc_connect(struct socket *sock, struct sockaddr_unsized *sockaddr,
		       int sockaddr_len, int flags)
{
	return pvc_bind(sock, sockaddr, sockaddr_len);
}

static int pvc_setsockopt(struct socket *sock, int level, int optname,
			  sockptr_t optval, unsigned int optlen)
{
	struct sock *sk = sock->sk;
	int error;

	lock_sock(sk);
	error = vcc_setsockopt(sock, level, optname, optval, optlen);
	release_sock(sk);
	return error;
}

static int pvc_getsockopt(struct socket *sock, int level, int optname,
			  sockopt_t *opt)
{
	struct sock *sk = sock->sk;
	int error;

	lock_sock(sk);
	error = vcc_getsockopt(sock, level, optname, opt);
	release_sock(sk);
	return error;
}

static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr,
		       int peer)
{
	struct sockaddr_atmpvc *addr;
	struct atm_vcc *vcc = ATM_SD(sock);

	if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags))
		return -ENOTCONN;

Annotation

Implementation Notes