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

📄 sock.c

📁 完整的1.0代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			break;				case SO_LINGER:				err=verify_area(VERIFY_WRITE,optval,sizeof(ling));			if(err)				return err;			err=verify_area(VERIFY_WRITE,optlen,sizeof(int));			if(err)				return err;			put_fs_long(sizeof(ling),(unsigned long *)optlen);			ling.l_onoff=sk->linger;			ling.l_linger=sk->lingertime;			memcpy_tofs(optval,&ling,sizeof(ling));			return 0;				case SO_SNDBUF:			val=sk->sndbuf;			break;				case SO_RCVBUF:			val =sk->rcvbuf;			break;		case SO_REUSEADDR:			val = sk->reuse;			break;		case SO_KEEPALIVE:			val = sk->keepopen;			break;		case SO_TYPE:			if (sk->prot == &tcp_prot) 				val = SOCK_STREAM;		  	else 		  		val = SOCK_DGRAM;			break;		case SO_ERROR:			val = sk->err;			sk->err = 0;			break;		case SO_OOBINLINE:			val = sk->urginline;			break;			case SO_NO_CHECK:			val = sk->no_check;			break;		case SO_PRIORITY:			val = sk->priority;			break;		default:			return(-ENOPROTOOPT);	}	err=verify_area(VERIFY_WRITE, optlen, sizeof(int));	if(err)  		return err;  	put_fs_long(sizeof(int),(unsigned long *) optlen);  	err=verify_area(VERIFY_WRITE, optval, sizeof(int));  	if(err)  		return err;  	put_fs_long(val,(unsigned long *)optval);  	return(0);}static intinet_listen(struct socket *sock, int backlog){  struct sock *sk;  sk = (struct sock *) sock->data;  if (sk == NULL) {	printk("Warning: sock->data = NULL: %d\n" ,__LINE__);	return(0);  }  /* We may need to bind the socket. */  if (sk->num == 0) {	sk->num = get_new_socknum(sk->prot, 0);	if (sk->num == 0) return(-EAGAIN);	put_sock(sk->num, sk);	sk->dummy_th.source = ntohs(sk->num);  }  /* We might as well re use these. */   sk->max_ack_backlog = backlog;  if (sk->state != TCP_LISTEN) {	sk->ack_backlog = 0;	sk->state = TCP_LISTEN;  }  return(0);}/* *	Default callbacks for user INET sockets. These just wake up *	the user owning the socket. */static void def_callback1(struct sock *sk){	if(!sk->dead)		wake_up_interruptible(sk->sleep);}static void def_callback2(struct sock *sk,int len){	if(!sk->dead)		wake_up_interruptible(sk->sleep);}static intinet_create(struct socket *sock, int protocol){  struct sock *sk;  struct proto *prot;  int err;  sk = (struct sock *) kmalloc(sizeof(*sk), GFP_KERNEL);  if (sk == NULL)   	return(-ENOMEM);  sk->num = 0;  sk->reuse = 0;  switch(sock->type) {	case SOCK_STREAM:	case SOCK_SEQPACKET:		if (protocol && protocol != IPPROTO_TCP) {			kfree_s((void *)sk, sizeof(*sk));			return(-EPROTONOSUPPORT);		}		protocol = IPPROTO_TCP;		sk->no_check = TCP_NO_CHECK;		prot = &tcp_prot;		break;	case SOCK_DGRAM:		if (protocol && protocol != IPPROTO_UDP) {			kfree_s((void *)sk, sizeof(*sk));			return(-EPROTONOSUPPORT);		}		protocol = IPPROTO_UDP;		sk->no_check = UDP_NO_CHECK;		prot=&udp_prot;		break;      	case SOCK_RAW:		if (!suser()) {			kfree_s((void *)sk, sizeof(*sk));			return(-EPERM);		}		if (!protocol) {			kfree_s((void *)sk, sizeof(*sk));			return(-EPROTONOSUPPORT);		}		prot = &raw_prot;		sk->reuse = 1;		sk->no_check = 0;	/*					 * Doesn't matter no checksum is					 * preformed anyway.					 */		sk->num = protocol;		break;	case SOCK_PACKET:		if (!suser()) {			kfree_s((void *)sk, sizeof(*sk));			return(-EPERM);		}		if (!protocol) {			kfree_s((void *)sk, sizeof(*sk));			return(-EPROTONOSUPPORT);		}		prot = &packet_prot;		sk->reuse = 1;		sk->no_check = 0;	/* Doesn't matter no checksum is					 * preformed anyway.					 */		sk->num = protocol;		break;	default:		kfree_s((void *)sk, sizeof(*sk));		return(-ESOCKTNOSUPPORT);  }  sk->socket = sock;#ifdef CONFIG_TCP_NAGLE_OFF  sk->nonagle = 1;#else      sk->nonagle = 0;#endif    sk->type = sock->type;  sk->protocol = protocol;  sk->wmem_alloc = 0;  sk->rmem_alloc = 0;  sk->sndbuf = SK_WMEM_MAX;  sk->rcvbuf = SK_RMEM_MAX;  sk->pair = NULL;  sk->opt = NULL;  sk->write_seq = 0;  sk->acked_seq = 0;  sk->copied_seq = 0;  sk->fin_seq = 0;  sk->urg_seq = 0;  sk->urg_data = 0;  sk->proc = 0;  sk->rtt = TCP_WRITE_TIME << 3;  sk->rto = TCP_WRITE_TIME;  sk->mdev = 0;  sk->backoff = 0;  sk->packets_out = 0;  sk->cong_window = 1; /* start with only sending one packet at a time. */  sk->cong_count = 0;  sk->ssthresh = 0;  sk->max_window = 0;  sk->urginline = 0;  sk->intr = 0;  sk->linger = 0;  sk->destroy = 0;  sk->priority = 1;  sk->shutdown = 0;  sk->keepopen = 0;  sk->zapped = 0;  sk->done = 0;  sk->ack_backlog = 0;  sk->window = 0;  sk->bytes_rcv = 0;  sk->state = TCP_CLOSE;  sk->dead = 0;  sk->ack_timed = 0;  sk->partial = NULL;  sk->user_mss = 0;  sk->debug = 0;  /* this is how many unacked bytes we will accept for this socket.  */  sk->max_unacked = 2048; /* needs to be at most 2 full packets. */  /* how many packets we should send before forcing an ack.      if this is set to zero it is the same as sk->delay_acks = 0 */  sk->max_ack_backlog = 0;  sk->inuse = 0;  sk->delay_acks = 0;  sk->wback = NULL;  sk->wfront = NULL;  sk->rqueue = NULL;  sk->mtu = 576;  sk->prot = prot;  sk->sleep = sock->wait;  sk->daddr = 0;  sk->saddr = my_addr();  sk->err = 0;  sk->next = NULL;  sk->pair = NULL;  sk->send_tail = NULL;  sk->send_head = NULL;  sk->timeout = 0;  sk->broadcast = 0;  sk->timer.data = (unsigned long)sk;  sk->timer.function = &net_timer;  sk->back_log = NULL;  sk->blog = 0;  sock->data =(void *) sk;  sk->dummy_th.doff = sizeof(sk->dummy_th)/4;  sk->dummy_th.res1=0;  sk->dummy_th.res2=0;  sk->dummy_th.urg_ptr = 0;  sk->dummy_th.fin = 0;  sk->dummy_th.syn = 0;  sk->dummy_th.rst = 0;  sk->dummy_th.psh = 0;  sk->dummy_th.ack = 0;  sk->dummy_th.urg = 0;  sk->dummy_th.dest = 0;  sk->ip_tos=0;  sk->ip_ttl=64;  	  sk->state_change = def_callback1;  sk->data_ready = def_callback2;  sk->write_space = def_callback1;  sk->error_report = def_callback1;  if (sk->num) {	/*	 * It assumes that any protocol which allows	 * the user to assign a number at socket	 * creation time automatically	 * shares.	 */	put_sock(sk->num, sk);	sk->dummy_th.source = ntohs(sk->num);  }  if (sk->prot->init) {	err = sk->prot->init(sk);	if (err != 0) {		destroy_sock(sk);		return(err);	}  }  return(0);}static intinet_dup(struct socket *newsock, struct socket *oldsock){  return(inet_create(newsock,		   ((struct sock *)(oldsock->data))->protocol));}/* The peer socket should always be NULL. */static intinet_release(struct socket *sock, struct socket *peer){  struct sock *sk;  sk = (struct sock *) sock->data;  if (sk == NULL) return(0);  DPRINTF((DBG_INET, "inet_release(sock = %X, peer = %X)\n", sock, peer));  sk->state_change(sk);  /* Start closing the connection.  This may take a while. */  /*   * If linger is set, we don't return until the close   * is complete.  Other wise we return immediately. The   * actually closing is done the same either way.   */  if (sk->linger == 0) {	sk->prot->close(sk,0);	sk->dead = 1;  } else {	DPRINTF((DBG_INET, "sk->linger set.\n"));	sk->prot->close(sk, 0);	cli();	if (sk->lingertime)		current->timeout = jiffies + HZ*sk->lingertime;	while(sk->state != TCP_CLOSE && current->timeout>0) {		interruptible_sleep_on(sk->sleep);		if (current->signal & ~current->blocked) {			break;#if 0			/* not working now - closes can't be restarted */			sti();			current->timeout=0;			return(-ERESTARTSYS);#endif		}	}	current->timeout=0;	sti();	sk->dead = 1;  }  sk->inuse = 1;  /* This will destroy it. */  release_sock(sk);  sock->data = NULL;  DPRINTF((DBG_INET, "inet_release returning\n"));  return(0);}/* this needs to be changed to dissallow   the rebinding of sockets.   What error   should it return? */static intinet_bind(struct socket *sock, struct sockaddr *uaddr,	       int addr_len){  struct sockaddr_in addr;  struct sock *sk, *sk2;  unsigned short snum;  int err;  sk = (struct sock *) sock->data;  if (sk == NULL) {	printk("Warning: sock->data = NULL: %d\n" ,__LINE__);	return(0);  }  /* check this error. */  if (sk->state != TCP_CLOSE) return(-EIO);  if (sk->num != 0) return(-EINVAL);  err=verify_area(VERIFY_READ, uaddr, addr_len);  if(err)  	return err;  memcpy_fromfs(&addr, uaddr, min(sizeof(addr), addr_len));  snum = ntohs(addr.sin_port);  DPRINTF((DBG_INET, "bind sk =%X to port = %d\n", sk, snum));  sk = (struct sock *) sock->data;  /*   * We can't just leave the socket bound wherever it is, it might   * be bound to a privileged port. However, since there seems to   * be a bug here, we will leave it if the port is not privileged.   */  if (snum == 0) {	snum = get_new_socknum(sk->prot, 0);  }  if (snum < PROT_SOCK && !suser()) return(-EACCES);  if (addr.sin_addr.s_addr!=0 && chk_addr(addr.sin_addr.s_addr)!=IS_MYADDR)  	return(-EADDRNOTAVAIL);	/* Source address MUST be ours! */  	  if (chk_addr(addr.sin_addr.s_addr) || addr.sin_addr.s_addr == 0)					sk->saddr = addr.sin_addr.s_addr;  DPRINTF((DBG_INET, "sock_array[%d] = %X:\n", snum &(SOCK_ARRAY_SIZE -1),	  		sk->prot->sock_array[snum &(SOCK_ARRAY_SIZE -1)]));  /* Make sure we are allowed to bind here. */  cli();outside_loop:  for(sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)];					sk2 != NULL; sk2 = sk2->next) {#if 	1	/* should be below! */	if (sk2->num != snum) continue;/*	if (sk2->saddr != sk->saddr) continue; */#endif	if (sk2->dead) {		destroy_sock(sk2);		goto outside_loop;	}	if (!sk->reuse) {		sti();		return(-EADDRINUSE);	}	if (sk2->num != snum) continue;		/* more than one */	if (sk2->saddr != sk->saddr) continue;	/* socket per slot ! -FB */	if (!sk2->reuse) {		sti();		return(-EADDRINUSE);	}  }  sti();  remove_sock(sk);  put_sock(snum, sk);  sk->dummy_th.source = ntohs(sk->num);  sk->daddr = 0;  sk->dummy_th.dest = 0;  return(0);}static intinet_connect(struct socket *sock, struct sockaddr * uaddr,		  int addr_len, int flags){  struct sock *sk;  int err;  sock->conn = NULL;  sk = (struct sock *) sock->data;  if (sk == NULL) {	printk("Warning: sock->data = NULL: %d\n" ,__LINE__);	return(0);  }  if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)  {	sock->state = SS_CONNECTED;  /* Connection completing after a connect/EINPROGRESS/select/connect */	return 0;	/* Rock and roll */  }  if (sock->state == SS_CONNECTING && sk->protocol == IPPROTO_TCP &&  	(flags & O_NONBLOCK))  	return -EALREADY;	/* Connecting is currently in progress */  	  if (sock->state != SS_CONNECTING) {	/* We may need to bind the socket. */	if (sk->num == 0) {		sk->num = get_new_socknum(sk->prot, 0);		if (sk->num == 0) 			return(-EAGAIN);		put_sock(sk->num, sk);		sk->dummy_th.source = htons(sk->num);	}	if (sk->prot->connect == NULL) 		return(-EOPNOTSUPP);  	err = sk->prot->connect(sk, (struct sockaddr_in *)uaddr, addr_len);	if (err < 0) return(err);  	sock->state = SS_CONNECTING;  }  if (sk->state != TCP_ESTABLISHED &&(flags & O_NONBLOCK))   	return(-EINPROGRESS);  cli(); /* avoid the race condition */  while(sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)   {	interruptible_sleep_on(sk->sleep);	if (current->signal & ~current->blocked) {		sti();		return(-ERESTARTSYS);	}	/* This fixes a nasty in the tcp/ip code. There is a hideous hassle with	   icmp error packets wanting to close a tcp or udp socket. */	if(sk->err && sk->protocol == IPPROTO_TCP)	{		sti();		sock->state = SS_UNCONNECTED;		err = -sk->err;		sk->err=0;		return err; /* set by tcp_err() */	}  }  sti();  sock->state = SS_CONNECTED;  if (sk->state != TCP_ESTABLISHED && sk->err) {	sock->state = SS_UNCONNECTED;	err=sk->err;	sk->err=0;	return(-err);  }  return(0);}static intinet_socketpair(struct socket *sock1, struct socket *sock2){  return(-EOPNOTSUPP);}static intinet_accept(struct socket *sock, struct socket *newsock, int flags){  struct sock *sk1, *sk2;  int err;  sk1 = (struct sock *) sock->data;  if (sk1 == NULL) {	printk("Warning: sock->data = NULL: %d\n" ,__LINE__);	return(0);  }  /*   * We've been passed an extra socket.   * We need to free it up because the tcp module creates   * it's own when it accepts one.   */  if (newsock->data) kfree_s(newsock->data, sizeof(struct sock));  newsock->data = NULL;  if (sk1->prot->accept == NULL) return(-EOPNOTSUPP);  /* Restore the state if we have been interrupted, and then returned. */  if (sk1->pair != NULL ) {	sk2 = sk1->pair;	sk1->pair = NULL;  } else {	sk2 = sk1->prot->accept(sk1,flags);	if (sk2 == NULL) {		if (sk1->err <= 0)			printk("Warning sock.c:sk1->err <= 0.  Returning non-error.\n");		err=sk1->err;		sk1->err=0;		return(-err);	}  }  newsock->data = (void *)sk2;  sk2->sleep = newsock->wait;  newsock->conn = NULL;  if (flags & O_NONBLOCK) return(0);  cli(); /* avoid the race. */  while(sk2->state == TCP_SYN_RECV) {	interruptible_sleep_on(sk2->sleep);	if (current->signal & ~current->blocked) {		sti();		sk1->pair = sk2;		sk2->sleep = NULL;		newsock->data = NULL;		return(-ERESTARTSYS);	}  }  sti();  if (sk2->state != TCP_ESTABLISHED && sk2->err > 0) {	err = -sk2->err;	sk2->err=0;	destroy_sock(sk2);	newsock->data = NULL;	return(err);  }  newsock->state = SS_CONNECTED;  return(0);}static intinet_getname(struct socket *sock, struct sockaddr *uaddr,		 int *uaddr_len, int peer){  struct sockaddr_in sin;  struct sock *sk;  int len;  int err;      err = verify_area(VERIFY_WRITE,uaddr_len,sizeof(long));  if(err)  	return err;  	  len=get_fs_long(uaddr_len);    err = verify_area(VERIFY_WRITE, uaddr, len);  if(err)  	return err;  	

⌨️ 快捷键说明

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