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

📄 tcp.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 5 页
字号:
342         }
343 #endif  
344         if (before(counted, skb->h.th->seq))    /* Found a hole so stops here */
345                 break;
346         sum = skb->len -(counted - skb->h.th->seq);     /* Length - header but start from where we are up to (avoid overlaps) */
347         if (skb->h.th->syn)
348                 sum++;
349         if (sum >= 0) {                                 /* Add it up, move on */
350                 amount += sum;
351                 if (skb->h.th->syn) amount--;
352                 counted += sum;
353         }
354         if (amount && skb->h.th->psh) break;
355         skb =(struct sk_buff *)skb->next;               /* Move along */
356   } while(skb != sk->rqueue);
357   if (amount && !sk->urginline && sk->urg_data &&
358       (sk->urg_seq - sk->copied_seq) <= (counted - sk->copied_seq))
359         amount--;               /* don't count urg data */
360   restore_flags(flags);
361   DPRINTF((DBG_TCP, "tcp readable returning %d bytes\n", amount));
362   if(sk->debug)
363         printk("got %lu bytes.\n",amount);
364   return(amount);
365 }
366 
367 
368 /*
369  *      Wait for a TCP event. Note the oddity with SEL_IN and reading. The
370  *      listening socket has a receive queue of sockets to accept.
371  */
372 
373 static int
374 tcp_select(struct sock *sk, int sel_type, select_table *wait)
375 {
376   DPRINTF((DBG_TCP, "tcp_select(sk=%X, sel_type = %d, wait = %X)\n",
377                                                 sk, sel_type, wait));
378 
379   sk->inuse = 1;
380   switch(sel_type) {
381         case SEL_IN:
382                 if(sk->debug)
383                         printk("select in");
384                 select_wait(sk->sleep, wait);
385                 if(sk->debug)
386                         printk("-select out");
387                 if (skb_peek(&sk->rqueue) != NULL) {
388                         if (sk->state == TCP_LISTEN || tcp_readable(sk)) {
389                                 release_sock(sk);
390                                 if(sk->debug)
391                                         printk("-select ok data\n");
392                                 return(1);
393                         }
394                 }
395                 if (sk->err != 0)       /* Receiver error */
396                 {
397                         release_sock(sk);
398                         if(sk->debug)
399                                 printk("-select ok error");
400                         return(1);
401                 }
402                 if (sk->shutdown & RCV_SHUTDOWN) {
403                         release_sock(sk);
404                         if(sk->debug)
405                                 printk("-select ok down\n");
406                         return(1);
407                 } else {
408                         release_sock(sk);
409                         if(sk->debug)
410                                 printk("-select fail\n");
411                         return(0);
412                 }
413         case SEL_OUT:
414                 select_wait(sk->sleep, wait);
415                 if (sk->shutdown & SEND_SHUTDOWN) {
416                         DPRINTF((DBG_TCP,
417                                 "write select on shutdown socket.\n"));
418 
419                         /* FIXME: should this return an error? */
420                         release_sock(sk);
421                         return(0);
422                 }
423 
424                 /*
425                  * FIXME:
426                  * Hack so it will probably be able to write
427                  * something if it says it's ok to write.
428                  */
429                 if (sk->prot->wspace(sk) >= sk->mss) {
430                         release_sock(sk);
431                         /* This should cause connect to work ok. */
432                         if (sk->state == TCP_SYN_RECV ||
433                             sk->state == TCP_SYN_SENT) return(0);
434                         return(1);
435                 }
436                 DPRINTF((DBG_TCP,
437                         "tcp_select: sleeping on write sk->wmem_alloc = %d, "
438                         "sk->packets_out = %d\n"
439                         "sk->wback = %X, sk->wfront = %X\n"
440                         "sk->write_seq = %u, sk->window_seq=%u\n", 
441                                 sk->wmem_alloc, sk->packets_out,
442                                 sk->wback, sk->wfront,
443                                 sk->write_seq, sk->window_seq));
444 
445                 release_sock(sk);
446                 return(0);
447         case SEL_EX:
448                 select_wait(sk->sleep,wait);
449                 if (sk->err || sk->urg_data) {
450                         release_sock(sk);
451                         return(1);
452                 }
453                 release_sock(sk);
454                 return(0);
455   }
456 
457   release_sock(sk);
458   return(0);
459 }
460 
461 
462 int
463 tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
464 {
465   int err;
466   DPRINTF((DBG_TCP, "tcp_ioctl(sk=%X, cmd = %d, arg=%X)\n", sk, cmd, arg));
467   switch(cmd) {
468         case DDIOCSDBG:
469                 return(dbg_ioctl((void *) arg, DBG_TCP));
470 
471         case TIOCINQ:
472 #ifdef FIXME    /* FIXME: */
473         case FIONREAD:
474 #endif
475                 {
476                         unsigned long amount;
477 
478                         if (sk->state == TCP_LISTEN) return(-EINVAL);
479 
480                         sk->inuse = 1;
481                         amount = tcp_readable(sk);
482                         release_sock(sk);
483                         DPRINTF((DBG_TCP, "returning %d\n", amount));
484                         err=verify_area(VERIFY_WRITE,(void *)arg,
485                                                    sizeof(unsigned long));
486                         if(err)
487                                 return err;
488                         put_fs_long(amount,(unsigned long *)arg);
489                         return(0);
490                 }
491         case SIOCATMARK:
492                 {
493                         int answ = sk->urg_data && sk->urg_seq == sk->copied_seq+1;
494 
495                         err = verify_area(VERIFY_WRITE,(void *) arg,
496                                                   sizeof(unsigned long));
497                         if (err)
498                                 return err;
499                         put_fs_long(answ,(int *) arg);
500                         return(0);
501                 }
502         case TIOCOUTQ:
503                 {
504                         unsigned long amount;
505 
506                         if (sk->state == TCP_LISTEN) return(-EINVAL);
507                         amount = sk->prot->wspace(sk);
508                         err=verify_area(VERIFY_WRITE,(void *)arg,
509                                                    sizeof(unsigned long));
510                         if(err)
511                                 return err;
512                         put_fs_long(amount,(unsigned long *)arg);
513                         return(0);
514                 }
515         default:
516                 return(-EINVAL);
517   }
518 }
519 
520 
521 /* This routine computes a TCP checksum. */
522 unsigned short
523 tcp_check(struct tcphdr *th, int len,
524           unsigned long saddr, unsigned long daddr)
525 {     
526   unsigned long sum;
527    
528   if (saddr == 0) saddr = my_addr();
529   print_th(th);
530   __asm__("\t addl %%ecx,%%ebx\n"
531           "\t adcl %%edx,%%ebx\n"
532           "\t adcl $0, %%ebx\n"
533           : "=b"(sum)
534           : ""(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256)
535           : "cx","bx","dx" );
536    
537   if (len > 3) {
538         __asm__("\tclc\n"
539                 "1:\n"
540                 "\t lodsl\n"
541                 "\t adcl %%eax, %%ebx\n"
542                 "\t loop 1b\n"
543                 "\t adcl $0, %%ebx\n"
544                 : "=b"(sum) , "=S"(th)
545                 : ""(sum), "c"(len/4) ,"1"(th)
546                 : "ax", "cx", "bx", "si" );
547   }
548    
549   /* Convert from 32 bits to 16 bits. */
550   __asm__("\t movl %%ebx, %%ecx\n"
551           "\t shrl $16,%%ecx\n"
552           "\t addw %%cx, %%bx\n"
553           "\t adcw $0, %%bx\n"
554           : "=b"(sum)
555           : ""(sum)
556           : "bx", "cx");
557    
558   /* Check for an extra word. */
559   if ((len & 2) != 0) {
560         __asm__("\t lodsw\n"
561                 "\t addw %%ax,%%bx\n"
562                 "\t adcw $0, %%bx\n"
563                 : "=b"(sum), "=S"(th)
564                 : ""(sum) ,"1"(th)
565                 : "si", "ax", "bx");
566   }
567    
568   /* Now check for the extra byte. */
569   if ((len & 1) != 0) {
570         __asm__("\t lodsb\n"
571                 "\t movb $0,%%ah\n"
572                 "\t addw %%ax,%%bx\n"
573                 "\t adcw $0, %%bx\n"
574                 : "=b"(sum)
575                 : ""(sum) ,"S"(th)
576                 : "si", "ax", "bx");
577   }
578    
579   /* We only want the bottom 16 bits, but we never cleared the top 16. */
580   return((~sum) & 0xffff);
581 }
582 
583 
584 void tcp_send_check(struct tcphdr *th, unsigned long saddr, 
585                 unsigned long daddr, int len, struct sock *sk)
586 {
587         th->check = 0;
588         th->check = tcp_check(th, len, saddr, daddr);
589         return;
590 }
591 
592 static void tcp_send_skb(struct sock *sk, struct sk_buff *skb)
593 {
594         int size;
595         struct tcphdr * th = skb->h.th;
596 
597         /* length of packet (not counting length of pre-tcp headers) */
598         size = skb->len - ((unsigned char *) th - skb->data);
599 
600         /* sanity check it.. */
601         if (size < sizeof(struct tcphdr) || size > skb->len) {
602                 printk("tcp_send_skb: bad skb (skb = %p, data = %p, th = %p, len = %lu)\n",
603                         skb, skb->data, th, skb->len);
604                 kfree_skb(skb, FREE_WRITE);
605                 return;
606         }
607 
608         /* If we have queued a header size packet.. */
609         if (size == sizeof(struct tcphdr)) {
610                 /* If its got a syn or fin its notionally included in the size..*/
611                 if(!th->syn && !th->fin) {
612                         printk("tcp_send_skb: attempt to queue a bogon.\n");
613                         kfree_skb(skb,FREE_WRITE);
614                         return;
615                 }
616         }
617   
618         /* We need to complete and send the packet. */
619         tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
620 
621         skb->h.seq = ntohl(th->seq) + size - 4*th->doff;
622         if (after(skb->h.seq, sk->window_seq) ||
623             (sk->retransmits && sk->timeout == TIME_WRITE) ||
624              sk->packets_out >= sk->cong_window) {
625                 DPRINTF((DBG_TCP, "sk->cong_window = %d, sk->packets_out = %d\n",
626                                         sk->cong_window, sk->packets_out));
627                 DPRINTF((DBG_TCP, "sk->write_seq = %d, sk->window_seq = %d\n",
628                                         sk->write_seq, sk->window_seq));
629                 skb->next = NULL;
630                 skb->magic = TCP_WRITE_QUEUE_MAGIC;
631                 if (sk->wback == NULL) {
632                         sk->wfront = skb;
633                 } else {
634                         sk->wback->next = skb;
635                 }
636                 sk->wback = skb;
637                 if (before(sk->window_seq, sk->wfront->h.seq) &&
638                     sk->send_head == NULL &&
639                     sk->ack_backlog == 0)
640                   reset_timer(sk, TIME_PROBE0, sk->rto);
641         } else {
642                 sk->sent_seq = sk->write_seq;
643                 sk->prot->queue_xmit(sk, skb->dev, skb, 0);
644         }
645 }
646 
647 struct sk_buff * tcp_dequeue_partial(struct sock * sk)
648 {
649         struct sk_buff * skb;
650         unsigned long flags;
651 
652         save_flags(flags);
653         cli();
654         skb = sk->partial;
655         if (skb) {
656                 sk->partial = NULL;
657                 del_timer(&sk->partial_timer);
658         }
659         restore_flags(flags);
660         return skb;
661 }
662 
663 static void tcp_send_partial(struct sock *sk)
664 {
665         struct sk_buff *skb;
666 
667         if (sk == NULL)
668                 return;
669         while ((skb = tcp_dequeue_partial(sk)) != NULL)
670                 tcp_send_skb(sk, skb);
671 }
672 
673 void tcp_enqueue_partial(struct sk_buff * skb, struct sock * sk)
674 {
675         struct sk_buff * tmp;
676         unsigned long flags;
677 
678         save_flags(flags);
679         cli();
680         tmp = sk->partial;
681         if (tmp)
682                 del_timer(&sk->partial_timer);

⌨️ 快捷键说明

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