⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket.c

📁 linux 1.0 源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  }  return(0);}/* * Perform a listen. Basically, we allow the protocol to do anything * necessary for a listen, and if that works, we mark the socket as * ready for listening. */static intsock_listen(int fd, int backlog){  struct socket *sock;  DPRINTF((net_debug, "NET: sock_listen: fd = %d\n", fd));  if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL)								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  if (sock->state != SS_UNCONNECTED) {	DPRINTF((net_debug, "NET: sock_listen: socket isn't unconnected\n"));	return(-EINVAL);  }  if (sock->ops && sock->ops->listen) sock->ops->listen(sock, backlog);  sock->flags |= SO_ACCEPTCON;  return(0);}/* * For accept, we attempt to create a new socket, set up the link * with the client, wake up the client, then return the new * connected fd. */static intsock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen){  struct file *file;  struct socket *sock, *newsock;  int i;  DPRINTF((net_debug, "NET: sock_accept: fd = %d\n", fd));  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))								return(-EBADF);    if (!(sock = sockfd_lookup(fd, &file))) return(-ENOTSOCK);  if (sock->state != SS_UNCONNECTED) {	DPRINTF((net_debug, "NET: sock_accept: socket isn't unconnected\n"));	return(-EINVAL);  }  if (!(sock->flags & SO_ACCEPTCON)) {	DPRINTF((net_debug,		"NET: sock_accept: socket not accepting connections!\n"));	return(-EINVAL);  }  if (!(newsock = sock_alloc(0))) {	printk("NET: sock_accept: no more sockets\n");	return(-EAGAIN);  }  newsock->type = sock->type;  newsock->ops = sock->ops;  if ((i = sock->ops->dup(newsock, sock)) < 0) {	sock_release(newsock);	return(i);  }  i = newsock->ops->accept(sock, newsock, file->f_flags);  if ( i < 0) {	sock_release(newsock);	return(i);  }  if ((fd = get_fd(SOCK_INODE(newsock))) < 0) {	sock_release(newsock);	return(-EINVAL);  }  DPRINTF((net_debug, "NET: sock_accept: connected socket 0x%x via 0x%x\n",							sock, newsock));  if (upeer_sockaddr)	newsock->ops->getname(newsock, upeer_sockaddr, upeer_addrlen, 1);  return(fd);}/* Attempt to connect to a socket with the server address. */static intsock_connect(int fd, struct sockaddr *uservaddr, int addrlen){  struct socket *sock;  struct file *file;  int i;  DPRINTF((net_debug, "NET: sock_connect: fd = %d\n", fd));  if (fd < 0 || fd >= NR_OPEN || (file=current->filp[fd]) == NULL)								return(-EBADF);    if (!(sock = sockfd_lookup(fd, &file))) return(-ENOTSOCK);  switch(sock->state) {	case SS_UNCONNECTED:		/* This is ok... continue with connect */		break;	case SS_CONNECTED:		/* Socket is already connected */		return -EISCONN;	case SS_CONNECTING:		/* Not yet connected... we will check this. */		return(sock->ops->connect(sock, uservaddr,					  addrlen, file->f_flags));	default:		DPRINTF((net_debug,			"NET: sock_connect: socket not unconnected\n"));		return(-EINVAL);  }  i = sock->ops->connect(sock, uservaddr, addrlen, file->f_flags);  if (i < 0) {	DPRINTF((net_debug, "NET: sock_connect: connect failed\n"));	return(i);  }  return(0);}static intsock_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len){  struct socket *sock;  DPRINTF((net_debug, "NET: sock_getsockname: fd = %d\n", fd));  if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL)								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  return(sock->ops->getname(sock, usockaddr, usockaddr_len, 0));}static intsock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len){  struct socket *sock;  DPRINTF((net_debug, "NET: sock_getpeername: fd = %d\n", fd));  if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL)			return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  return(sock->ops->getname(sock, usockaddr, usockaddr_len, 1));}static intsock_send(int fd, void * buff, int len, unsigned flags){  struct socket *sock;  struct file *file;  DPRINTF((net_debug,	"NET: sock_send(fd = %d, buff = %X, len = %d, flags = %X)\n",       							fd, buff, len, flags));  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  return(sock->ops->send(sock, buff, len, (file->f_flags & O_NONBLOCK), flags));}static intsock_sendto(int fd, void * buff, int len, unsigned flags,	   struct sockaddr *addr, int addr_len){  struct socket *sock;  struct file *file;  DPRINTF((net_debug,	"NET: sock_sendto(fd = %d, buff = %X, len = %d, flags = %X,"	 " addr=%X, alen = %d\n", fd, buff, len, flags, addr, addr_len));  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  return(sock->ops->sendto(sock, buff, len, (file->f_flags & O_NONBLOCK),			   flags, addr, addr_len));}static intsock_recv(int fd, void * buff, int len, unsigned flags){  struct socket *sock;  struct file *file;  DPRINTF((net_debug,	"NET: sock_recv(fd = %d, buff = %X, len = %d, flags = %X)\n",							fd, buff, len, flags));  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  return(sock->ops->recv(sock, buff, len,(file->f_flags & O_NONBLOCK), flags));}static intsock_recvfrom(int fd, void * buff, int len, unsigned flags,	     struct sockaddr *addr, int *addr_len){  struct socket *sock;  struct file *file;  DPRINTF((net_debug,	"NET: sock_recvfrom(fd = %d, buff = %X, len = %d, flags = %X,"	" addr=%X, alen=%X\n", fd, buff, len, flags, addr, addr_len));  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  return(sock->ops->recvfrom(sock, buff, len, (file->f_flags & O_NONBLOCK),			     flags, addr, addr_len));}static intsock_setsockopt(int fd, int level, int optname, char *optval, int optlen){  struct socket *sock;  struct file *file;	  DPRINTF((net_debug, "NET: sock_setsockopt(fd=%d, level=%d, optname=%d,\n",							fd, level, optname));  DPRINTF((net_debug, "                     optval = %X, optlen = %d)\n",							optval, optlen));  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  return(sock->ops->setsockopt(sock, level, optname, optval, optlen));}static intsock_getsockopt(int fd, int level, int optname, char *optval, int *optlen){  struct socket *sock;  struct file *file;  DPRINTF((net_debug, "NET: sock_getsockopt(fd=%d, level=%d, optname=%d,\n",						fd, level, optname));  DPRINTF((net_debug, "                     optval = %X, optlen = %X)\n",						optval, optlen));  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);	      if (!sock->ops || !sock->ops->getsockopt) return(0);  return(sock->ops->getsockopt(sock, level, optname, optval, optlen));}static intsock_shutdown(int fd, int how){  struct socket *sock;  struct file *file;  DPRINTF((net_debug, "NET: sock_shutdown(fd = %d, how = %d)\n", fd, how));  if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))								return(-EBADF);  if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);  return(sock->ops->shutdown(sock, how));}intsock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg){  struct socket *sock;  sock = socki_lookup (filp->f_inode);  if (sock != NULL && sock->ops != NULL && sock->ops->fcntl != NULL)				return(sock->ops->fcntl(sock, cmd, arg));  return(-EINVAL);}/* * System call vectors. Since I (RIB) want to rewrite sockets as streams, * we have this level of indirection. Not a lot of overhead, since more of * the work is done via read/write/select directly. */asmlinkage intsys_socketcall(int call, unsigned long *args){  int er;  switch(call) {	case SYS_SOCKET:		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));		if(er)			return er;		return(sock_socket(get_fs_long(args+0),				   get_fs_long(args+1),				   get_fs_long(args+2)));	case SYS_BIND:		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));		if(er)			return er;		return(sock_bind(get_fs_long(args+0),				 (struct sockaddr *)get_fs_long(args+1),				 get_fs_long(args+2)));	case SYS_CONNECT:		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));		if(er)			return er;		return(sock_connect(get_fs_long(args+0),				    (struct sockaddr *)get_fs_long(args+1),				    get_fs_long(args+2)));	case SYS_LISTEN:		er=verify_area(VERIFY_READ, args, 2 * sizeof(long));		if(er)			return er;		return(sock_listen(get_fs_long(args+0),				   get_fs_long(args+1)));	case SYS_ACCEPT:		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));		if(er)			return er;		return(sock_accept(get_fs_long(args+0),				   (struct sockaddr *)get_fs_long(args+1),				   (int *)get_fs_long(args+2)));	case SYS_GETSOCKNAME:		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));		if(er)			return er;		return(sock_getsockname(get_fs_long(args+0),					(struct sockaddr *)get_fs_long(args+1),					(int *)get_fs_long(args+2)));	case SYS_GETPEERNAME:		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));		if(er)			return er;		return(sock_getpeername(get_fs_long(args+0),					(struct sockaddr *)get_fs_long(args+1),					(int *)get_fs_long(args+2)));	case SYS_SOCKETPAIR:		er=verify_area(VERIFY_READ, args, 4 * sizeof(long));		if(er)			return er;		return(sock_socketpair(get_fs_long(args+0),				       get_fs_long(args+1),				       get_fs_long(args+2),				       (unsigned long *)get_fs_long(args+3)));	case SYS_SEND:		er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));		if(er)			return er;		return(sock_send(get_fs_long(args+0),				 (void *)get_fs_long(args+1),				 get_fs_long(args+2),				 get_fs_long(args+3)));	case SYS_SENDTO:		er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));		if(er)			return er;		return(sock_sendto(get_fs_long(args+0),				   (void *)get_fs_long(args+1),				   get_fs_long(args+2),				   get_fs_long(args+3),				   (struct sockaddr *)get_fs_long(args+4),				   get_fs_long(args+5)));	case SYS_RECV:		er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));		if(er)			return er;		return(sock_recv(get_fs_long(args+0),				 (void *)get_fs_long(args+1),				 get_fs_long(args+2),				 get_fs_long(args+3)));	case SYS_RECVFROM:		er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));		if(er)			return er;		return(sock_recvfrom(get_fs_long(args+0),				     (void *)get_fs_long(args+1),				     get_fs_long(args+2),				     get_fs_long(args+3),				     (struct sockaddr *)get_fs_long(args+4),				     (int *)get_fs_long(args+5)));	case SYS_SHUTDOWN:		er=verify_area(VERIFY_READ, args, 2* sizeof(unsigned long));		if(er)			return er;		return(sock_shutdown(get_fs_long(args+0),				     get_fs_long(args+1)));	case SYS_SETSOCKOPT:		er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));		if(er)			return er;		return(sock_setsockopt(get_fs_long(args+0),				       get_fs_long(args+1),				       get_fs_long(args+2),				       (char *)get_fs_long(args+3),				       get_fs_long(args+4)));	case SYS_GETSOCKOPT:		er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));		if(er)			return er;		return(sock_getsockopt(get_fs_long(args+0),				       get_fs_long(args+1),				       get_fs_long(args+2),				       (char *)get_fs_long(args+3),				       (int *)get_fs_long(args+4)));	default:		return(-EINVAL);  }}static intnet_ioctl(unsigned int cmd, unsigned long arg){  int er;  switch(cmd) {	case DDIOCSDBG:		er=verify_area(VERIFY_READ, (void *)arg, sizeof(long));		if(er)			return er;		net_debug = get_fs_long((long *)arg);		if (net_debug != 0 && net_debug != 1) {			net_debug = 0;			return(-EINVAL);		}		return(0);	default:		return(-EINVAL);  }  /*NOTREACHED*/  return(0);}/* * Handle the IOCTL system call for the NET devices.  This basically * means I/O control for the SOCKET layer (future expansions could be * a variable number of socket table entries, et al), and for the more * general protocols like ARP.  The latter currently lives in the INET * module, so we have to get ugly a tiny little bit.  Later... -FvK */static intnet_fioctl(struct inode *inode, struct file *file,	   unsigned int cmd, unsigned long arg){  extern int arp_ioctl(unsigned int, void *);  /* Dispatch on the minor device. */  switch(MINOR(inode->i_rdev)) {	case 0:		/* NET (SOCKET) */		DPRINTF((net_debug, "NET: SOCKET level I/O control request.\n"));		return(net_ioctl(cmd, arg));#ifdef CONFIG_INET	case 1:		/* ARP */		DPRINTF((net_debug, "NET: ARP level I/O control request.\n"));		return(arp_ioctl(cmd, (void *) arg));#endif	default:		return(-ENODEV);  }  /*NOTREACHED*/  return(-EINVAL);}static struct file_operations net_fops = {  NULL,		/* LSEEK	*/  NULL,		/* READ		*/  NULL,		/* WRITE	*/  NULL,		/* READDIR	*/  NULL,		/* SELECT	*/  net_fioctl,	/* IOCTL	*/  NULL,		/* MMAP		*/  NULL,		/* OPEN		*/  NULL		/* CLOSE	*/};/* * This function is called by a protocol handler that wants to * advertise its address family, and have it linked into the * SOCKET module. */intsock_register(int family, struct proto_ops *ops){  int i;  cli();  for(i = 0; i < NPROTO; i++) {	if (pops[i] != NULL) continue;	pops[i] = ops;	pops[i]->family = family;	sti();	DPRINTF((net_debug, "NET: Installed protocol %d in slot %d (0x%X)\n",						family, i, (long)ops));	return(i);  }  sti();  return(-ENOMEM);}voidsock_init(void){  struct socket *sock;  int i;  /* Set up our SOCKET VFS major device. */  if (register_chrdev(SOCKET_MAJOR, "socket", &net_fops) < 0) {	printk("NET: cannot register major device %d!\n", SOCKET_MAJOR);	return;  }  /* Release all sockets. */  for (sock = sockets; sock <= last_socket; ++sock) sock->state = SS_FREE;  /* Initialize all address (protocol) families. */  for (i = 0; i < NPROTO; ++i) pops[i] = NULL;  /* Initialize the DDI module. */  ddi_init();  /* Initialize the ARP module. */#if 0  arp_init();#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -