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

📄 tcp.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 5 页
字号:
683         sk->partial = skb;
684         sk->partial_timer.expires = HZ;
685         sk->partial_timer.function = (void (*)(unsigned long)) tcp_send_partial;
686         sk->partial_timer.data = (unsigned long) sk;
687         add_timer(&sk->partial_timer);
688         restore_flags(flags);
689         if (tmp)
690                 tcp_send_skb(sk, tmp);
691 }
692 
693 
694 /* This routine sends an ack and also updates the window. */
695 static void
696 tcp_send_ack(unsigned long sequence, unsigned long ack,
697              struct sock *sk,
698              struct tcphdr *th, unsigned long daddr)
699 {
700   struct sk_buff *buff;
701   struct tcphdr *t1;
702   struct device *dev = NULL;
703   int tmp;
704 
705   if(sk->zapped)
706         return;         /* We have been reset, we may not send again */
707   /*
708    * We need to grab some memory, and put together an ack,
709    * and then put it into the queue to be sent.
710    */
711   buff = sk->prot->wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC);
712   if (buff == NULL) {
713         /* Force it to send an ack. */
714         sk->ack_backlog++;
715         if (sk->timeout != TIME_WRITE && tcp_connected(sk->state)) {
716                 reset_timer(sk, TIME_WRITE, 10);
717         }
718 if (inet_debug == DBG_SLIP) printk("\rtcp_ack: malloc failed\n");
719         return;
720   }
721 
722   buff->mem_addr = buff;
723   buff->mem_len = MAX_ACK_SIZE;
724   buff->len = sizeof(struct tcphdr);
725   buff->sk = sk;
726   t1 =(struct tcphdr *) buff->data;
727 
728   /* Put in the IP header and routing stuff. */
729   tmp = sk->prot->build_header(buff, sk->saddr, daddr, &dev,
730                                 IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
731   if (tmp < 0) {
732         buff->free=1;
733         sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
734 if (inet_debug == DBG_SLIP) printk("\rtcp_ack: build_header failed\n");
735         return;
736   }
737   buff->len += tmp;
738   t1 =(struct tcphdr *)((char *)t1 +tmp);
739 
740   /* FIXME: */
741   memcpy(t1, th, sizeof(*t1)); /* this should probably be removed */
742 
743   /* swap the send and the receive. */
744   t1->dest = th->source;
745   t1->source = th->dest;
746   t1->seq = ntohl(sequence);
747   t1->ack = 1;
748   sk->window = tcp_select_window(sk);/*sk->prot->rspace(sk);*/
749   t1->window = ntohs(sk->window);
750   t1->res1 = 0;
751   t1->res2 = 0;
752   t1->rst = 0;
753   t1->urg = 0;
754   t1->syn = 0;
755   t1->psh = 0;
756   t1->fin = 0;
757   if (ack == sk->acked_seq) {
758         sk->ack_backlog = 0;
759         sk->bytes_rcv = 0;
760         sk->ack_timed = 0;
761         if (sk->send_head == NULL && sk->wfront == NULL && sk->timeout == TIME_WRITE) 
762         {
763                 if(sk->keepopen)
764                         reset_timer(sk,TIME_KEEPOPEN,TCP_TIMEOUT_LEN);
765                 else
766                         delete_timer(sk);
767         }
768   }
769   t1->ack_seq = ntohl(ack);
770   t1->doff = sizeof(*t1)/4;
771   tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), sk);
772   if (sk->debug)
773          printk("\rtcp_ack: seq %lx ack %lx\n", sequence, ack);
774   sk->prot->queue_xmit(sk, dev, buff, 1);
775 }
776 
777 
778 /* This routine builds a generic TCP header. */
779 static int
780 tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
781 {
782 
783   /* FIXME: want to get rid of this. */
784   memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
785   th->seq = htonl(sk->write_seq);
786   th->psh =(push == 0) ? 1 : 0;
787   th->doff = sizeof(*th)/4;
788   th->ack = 1;
789   th->fin = 0;
790   sk->ack_backlog = 0;
791   sk->bytes_rcv = 0;
792   sk->ack_timed = 0;
793   th->ack_seq = htonl(sk->acked_seq);
794   sk->window = tcp_select_window(sk)/*sk->prot->rspace(sk)*/;
795   th->window = htons(sk->window);
796 
797   return(sizeof(*th));
798 }
799 
800 /*
801  * This routine copies from a user buffer into a socket,
802  * and starts the transmit system.
803  */
804 static int
805 tcp_write(struct sock *sk, unsigned char *from,
806           int len, int nonblock, unsigned flags)
807 {
808   int copied = 0;
809   int copy;
810   int tmp;
811   struct sk_buff *skb;
812   struct sk_buff *send_tmp;
813   unsigned char *buff;
814   struct proto *prot;
815   struct device *dev = NULL;
816 
817   DPRINTF((DBG_TCP, "tcp_write(sk=%X, from=%X, len=%d, nonblock=%d, flags=%X)\n",
818                                         sk, from, len, nonblock, flags));
819 
820   sk->inuse=1;
821   prot = sk->prot;
822   while(len > 0) {
823         if (sk->err) {                  /* Stop on an error */
824                 release_sock(sk);
825                 if (copied) return(copied);
826                 tmp = -sk->err;
827                 sk->err = 0;
828                 return(tmp);
829         }
830 
831         /* First thing we do is make sure that we are established. */    
832         if (sk->shutdown & SEND_SHUTDOWN) {
833                 release_sock(sk);
834                 sk->err = EPIPE;
835                 if (copied) return(copied);
836                 sk->err = 0;
837                 return(-EPIPE);
838         }
839 
840 
841         /* Wait for a connection to finish. */
842         
843         while(sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) {
844                 if (sk->err) {
845                         release_sock(sk);
846                         if (copied) return(copied);
847                         tmp = -sk->err;
848                         sk->err = 0;
849                         return(tmp);
850                 }
851 
852                 if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) {
853                         release_sock(sk);
854                         DPRINTF((DBG_TCP, "tcp_write: return 1\n"));
855                         if (copied) return(copied);
856 
857                         if (sk->err) {
858                                 tmp = -sk->err;
859                                 sk->err = 0;
860                                 return(tmp);
861                         }
862 
863                         if (sk->keepopen) {
864                                 send_sig(SIGPIPE, current, 0);
865                         }
866                         return(-EPIPE);
867                 }
868 
869                 if (nonblock || copied) {
870                         release_sock(sk);
871                         DPRINTF((DBG_TCP, "tcp_write: return 2\n"));
872                         if (copied) return(copied);
873                         return(-EAGAIN);
874                 }
875 
876                 release_sock(sk);
877                 cli();
878                 if (sk->state != TCP_ESTABLISHED &&
879                     sk->state != TCP_CLOSE_WAIT && sk->err == 0) {
880                         interruptible_sleep_on(sk->sleep);
881                         if (current->signal & ~current->blocked) {
882                                 sti();
883                                 DPRINTF((DBG_TCP, "tcp_write: return 3\n"));
884                                 if (copied) return(copied);
885                                 return(-ERESTARTSYS);
886                         }
887                 }
888                 sk->inuse = 1;
889                 sti();
890         }
891 
892 /*
893  * The following code can result in copy <= if sk->mss is ever
894  * decreased.  It shouldn't be.  sk->mss is min(sk->mtu, sk->max_window).
895  * sk->mtu is constant once SYN processing is finished.  I.e. we
896  * had better not get here until we've seen his SYN and at least one
897  * valid ack.  (The SYN sets sk->mtu and the ack sets sk->max_window.)
898  * But ESTABLISHED should guarantee that.  sk->max_window is by definition
899  * non-decreasing.  Note that any ioctl to set user_mss must be done
900  * before the exchange of SYN's.  If the initial ack from the other
901  * end has a window of 0, max_window and thus mss will both be 0.
902  */
903 
904         /* Now we need to check if we have a half built packet. */
905         if ((skb = tcp_dequeue_partial(sk)) != NULL) {
906                 int hdrlen;
907 
908                  /* IP header + TCP header */
909                 hdrlen = ((unsigned long)skb->h.th - (unsigned long)skb->data)
910                          + sizeof(struct tcphdr);
911 
912                 /* Add more stuff to the end of skb->len */
913                 if (!(flags & MSG_OOB)) {
914                         copy = min(sk->mss - (skb->len - hdrlen), len);
915                         /* FIXME: this is really a bug. */
916                         if (copy <= 0) {
917                           printk("TCP: **bug**: \"copy\" <= 0!!\n");
918                           copy = 0;
919                         }
920           
921                         memcpy_fromfs(skb->data + skb->len, from, copy);
922                         skb->len += copy;
923                         from += copy;
924                         copied += copy;
925                         len -= copy;
926                         sk->write_seq += copy;
927                       }
928                 if ((skb->len - hdrlen) >= sk->mss ||
929                     (flags & MSG_OOB) ||
930                     !sk->packets_out)
931                         tcp_send_skb(sk, skb);
932                 else
933                         tcp_enqueue_partial(skb, sk);
934                 continue;
935         }
936 
937         /*
938          * We also need to worry about the window.
939          * If window < 1/2 the maximum window we've seen from this
940          *   host, don't use it.  This is sender side
941          *   silly window prevention, as specified in RFC1122.
942          *   (Note that this is diffferent than earlier versions of
943          *   SWS prevention, e.g. RFC813.).  What we actually do is 
944          *   use the whole MSS.  Since the results in the right
945          *   edge of the packet being outside the window, it will
946          *   be queued for later rather than sent.
947          */
948 
949         copy = sk->window_seq - sk->write_seq;
950         if (copy <= 0 || copy < (sk->max_window >> 1) || copy > sk->mss)
951                 copy = sk->mss;
952         if (copy > len)
953                 copy = len;
954 
955   /* We should really check the window here also. */
956         send_tmp = NULL;
957         if (copy < sk->mss && !(flags & MSG_OOB)) {
958         /* We will release the socket incase we sleep here. */
959           release_sock(sk);
960           /* NB: following must be mtu, because mss can be increased.
961            * mss is always <= mtu */
962           skb = prot->wmalloc(sk, sk->mtu + 128 + prot->max_header + sizeof(*skb), 0, GFP_KERNEL);
963           sk->inuse = 1;
964           send_tmp = skb;
965         } else {
966                 /* We will release the socket incase we sleep here. */
967           release_sock(sk);
968           skb = prot->wmalloc(sk, copy + prot->max_header + sizeof(*skb), 0, GFP_KERNEL);
969           sk->inuse = 1;
970         }
971 
972         /* If we didn't get any memory, we need to sleep. */
973         if (skb == NULL) {
974                 if (nonblock /* || copied */) {
975                         release_sock(sk);
976                         DPRINTF((DBG_TCP, "tcp_write: return 4\n"));
977                         if (copied) return(copied);
978                         return(-EAGAIN);
979                 }
980 
981                 /* FIXME: here is another race condition. */
982                 tmp = sk->wmem_alloc;
983                 release_sock(sk);
984                 cli();
985                 /* Again we will try to avoid it. */
986                 if (tmp <= sk->wmem_alloc &&
987                   (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)
988                                 && sk->err == 0) {
989                         interruptible_sleep_on(sk->sleep);
990                         if (current->signal & ~current->blocked) {
991                                 sti();
992                                 DPRINTF((DBG_TCP, "tcp_write: return 5\n"));
993                                 if (copied) return(copied);
994                                 return(-ERESTARTSYS);
995                         }
996                 }
997                 sk->inuse = 1;
998                 sti();
999                 continue;
1000         }
1001 
1002         skb->len = 0;
1003         skb->sk = sk;
1004         skb->free = 0;
1005 
1006         buff = skb->data;
1007 
1008         /*
1009          * FIXME: we need to optimize this.
1010          * Perhaps some hints here would be good.
1011          */
1012         tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
1013                                  IPPROTO_TCP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
1014         if (tmp < 0 ) {
1015                 prot->wfree(sk, skb->mem_addr, skb->mem_len);
1016                 release_sock(sk);
1017                 DPRINTF((DBG_TCP, "tcp_write: return 6\n"));
1018                 if (copied) return(copied);
1019                 return(tmp);
1020         }
1021         skb->len += tmp;
1022         skb->dev = dev;
1023         buff += tmp;

⌨️ 快捷键说明

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