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

📄 tcp.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 5 页
字号:
1365                         copied = -sk->err;
1366                         sk->err = 0;
1367                         break;
1368                 }
1369 
1370                 if (sk->state == TCP_CLOSE) {
1371                         if (!sk->done) {
1372                                 sk->done = 1;
1373                                 break;
1374                         }
1375                         copied = -ENOTCONN;
1376                         break;
1377                 }
1378 
1379                 if (sk->shutdown & RCV_SHUTDOWN) {
1380                         sk->done = 1;
1381                         break;
1382                 }
1383                         
1384                 if (nonblock) {
1385                         copied = -EAGAIN;
1386                         break;
1387                 }
1388 
1389                 cleanup_rbuf(sk);
1390                 release_sock(sk);
1391                 schedule();
1392                 sk->inuse = 1;
1393 
1394                 if (current->signal & ~current->blocked) {
1395                         copied = -ERESTARTSYS;
1396                         break;
1397                 }
1398                 continue;
1399 
1400         found_ok_skb:
1401                 /* Ok so how much can we use ? */
1402                 used = skb->len - offset;
1403                 if (len < used)
1404                         used = len;
1405                 /* do we have urgent data here? */
1406                 if (sk->urg_data) {
1407                         unsigned long urg_offset = sk->urg_seq - (1 + *seq);
1408                         if (urg_offset < used) {
1409                                 if (!urg_offset) {
1410                                         if (!sk->urginline) {
1411                                                 ++*seq;
1412                                                 offset++;
1413                                                 used--;
1414                                         }
1415                                 } else
1416                                         used = urg_offset;
1417                         }
1418                 }
1419                 /* Copy it */
1420                 memcpy_tofs(to,((unsigned char *)skb->h.th) +
1421                         skb->h.th->doff*4 + offset, used);
1422                 copied += used;
1423                 len -= used;
1424                 to += used;
1425                 *seq += used;
1426                 if (after(sk->copied_seq+1,sk->urg_seq))
1427                         sk->urg_data = 0;
1428                 if (!(flags & MSG_PEEK) && (used + offset >= skb->len))
1429                         skb->used = 1;
1430         }
1431         remove_wait_queue(sk->sleep, &wait);
1432         current->state = TASK_RUNNING;
1433 
1434         /* Clean up data we have read: This will do ACK frames */
1435         cleanup_rbuf(sk);
1436         release_sock(sk);
1437         DPRINTF((DBG_TCP, "tcp_read: returning %d\n", copied));
1438         return copied;
1439 }
1440 
1441  
1442 /*
1443  * Send a FIN without closing the connection.
1444  * Not called at interrupt time.
1445  */
1446 void
1447 tcp_shutdown(struct sock *sk, int how)
1448 {
1449   struct sk_buff *buff;
1450   struct tcphdr *t1, *th;
1451   struct proto *prot;
1452   int tmp;
1453   struct device *dev = NULL;
1454 
1455   /*
1456    * We need to grab some memory, and put together a FIN,
1457    * and then put it into the queue to be sent.
1458    * FIXME:
1459    *    Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
1460    *    Most of this is guesswork, so maybe it will work...
1461    */
1462   /* If we've already sent a FIN, return. */
1463   if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) return;
1464   if (!(how & SEND_SHUTDOWN)) return;
1465   sk->inuse = 1;
1466 
1467   /* Clear out any half completed packets. */
1468   if (sk->partial)
1469         tcp_send_partial(sk);
1470 
1471   prot =(struct proto *)sk->prot;
1472   th =(struct tcphdr *)&sk->dummy_th;
1473   release_sock(sk); /* incase the malloc sleeps. */
1474   buff = prot->wmalloc(sk, MAX_RESET_SIZE,1 , GFP_KERNEL);
1475   if (buff == NULL) return;
1476   sk->inuse = 1;
1477 
1478   DPRINTF((DBG_TCP, "tcp_shutdown_send buff = %X\n", buff));
1479   buff->mem_addr = buff;
1480   buff->mem_len = MAX_RESET_SIZE;
1481   buff->sk = sk;
1482   buff->len = sizeof(*t1);
1483   t1 =(struct tcphdr *) buff->data;
1484 
1485   /* Put in the IP header and routing stuff. */
1486   tmp = prot->build_header(buff,sk->saddr, sk->daddr, &dev,
1487                            IPPROTO_TCP, sk->opt,
1488                            sizeof(struct tcphdr),sk->ip_tos,sk->ip_ttl);
1489   if (tmp < 0) {
1490         buff->free=1;
1491         prot->wfree(sk,buff->mem_addr, buff->mem_len);
1492         release_sock(sk);
1493         DPRINTF((DBG_TCP, "Unable to build header for fin.\n"));
1494         return;
1495   }
1496 
1497   t1 =(struct tcphdr *)((char *)t1 +tmp);
1498   buff->len += tmp;
1499   buff->dev = dev;
1500   memcpy(t1, th, sizeof(*t1));
1501   t1->seq = ntohl(sk->write_seq);
1502   sk->write_seq++;
1503   buff->h.seq = sk->write_seq;
1504   t1->ack = 1;
1505   t1->ack_seq = ntohl(sk->acked_seq);
1506   t1->window = ntohs(sk->window=tcp_select_window(sk)/*sk->prot->rspace(sk)*/);
1507   t1->fin = 1;
1508   t1->rst = 0;
1509   t1->doff = sizeof(*t1)/4;
1510   tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
1511 
1512   /*
1513    * Can't just queue this up.
1514    * It should go at the end of the write queue.
1515    */
1516   if (sk->wback != NULL) {
1517         buff->free=0;   
1518         buff->next = NULL;
1519         sk->wback->next = buff;
1520         sk->wback = buff;
1521         buff->magic = TCP_WRITE_QUEUE_MAGIC;
1522   } else {
1523         sk->sent_seq = sk->write_seq;
1524         sk->prot->queue_xmit(sk, dev, buff, 0);
1525   }
1526 
1527   if (sk->state == TCP_ESTABLISHED) sk->state = TCP_FIN_WAIT1;
1528     else sk->state = TCP_FIN_WAIT2;
1529 
1530   release_sock(sk);
1531 }
1532 
1533 
1534 static int
1535 tcp_recvfrom(struct sock *sk, unsigned char *to,
1536              int to_len, int nonblock, unsigned flags,
1537              struct sockaddr_in *addr, int *addr_len)
1538 {
1539   struct sockaddr_in sin;
1540   int len;
1541   int err;
1542   int result;
1543   
1544   /* Have to check these first unlike the old code. If 
1545      we check them after we lose data on an error
1546      which is wrong */
1547   err = verify_area(VERIFY_WRITE,addr_len,sizeof(long));
1548   if(err)
1549         return err;
1550   len = get_fs_long(addr_len);
1551   if(len > sizeof(sin))
1552         len = sizeof(sin);
1553   err=verify_area(VERIFY_WRITE, addr, len);  
1554   if(err)
1555         return err;
1556         
1557   result=tcp_read(sk, to, to_len, nonblock, flags);
1558 
1559   if (result < 0) return(result);
1560   
1561   sin.sin_family = AF_INET;
1562   sin.sin_port = sk->dummy_th.dest;
1563   sin.sin_addr.s_addr = sk->daddr;
1564 
1565   memcpy_tofs(addr, &sin, len);
1566   put_fs_long(len, addr_len);
1567   return(result);
1568 }
1569 
1570 
1571 /* This routine will send an RST to the other tcp. */
1572 static void
1573 tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
1574           struct proto *prot, struct options *opt, struct device *dev, int tos, int ttl)
1575 {
1576   struct sk_buff *buff;
1577   struct tcphdr *t1;
1578   int tmp;
1579 
1580   /*
1581    * We need to grab some memory, and put together an RST,
1582    * and then put it into the queue to be sent.
1583    */
1584   buff = prot->wmalloc(NULL, MAX_RESET_SIZE, 1, GFP_ATOMIC);
1585   if (buff == NULL) 
1586         return;
1587 
1588   DPRINTF((DBG_TCP, "tcp_reset buff = %X\n", buff));
1589   buff->mem_addr = buff;
1590   buff->mem_len = MAX_RESET_SIZE;
1591   buff->len = sizeof(*t1);
1592   buff->sk = NULL;
1593   buff->dev = dev;
1594 
1595   t1 =(struct tcphdr *) buff->data;
1596 
1597   /* Put in the IP header and routing stuff. */
1598   tmp = prot->build_header(buff, saddr, daddr, &dev, IPPROTO_TCP, opt,
1599                            sizeof(struct tcphdr),tos,ttl);
1600   if (tmp < 0) {
1601         buff->free = 1;
1602         prot->wfree(NULL, buff->mem_addr, buff->mem_len);
1603         return;
1604   }
1605   t1 =(struct tcphdr *)((char *)t1 +tmp);
1606   buff->len += tmp;
1607   memcpy(t1, th, sizeof(*t1));
1608 
1609   /* Swap the send and the receive. */
1610   t1->dest = th->source;
1611   t1->source = th->dest;
1612   t1->rst = 1;  
1613   t1->window = 0;
1614   
1615   if(th->ack)
1616   {
1617         t1->ack = 0;
1618         t1->seq = th->ack_seq;
1619         t1->ack_seq = 0;
1620   }
1621   else
1622   {
1623         t1->ack = 1;
1624         if(!th->syn)
1625                 t1->ack_seq=htonl(th->seq);
1626         else
1627                 t1->ack_seq=htonl(th->seq+1);
1628         t1->seq=0;
1629   }
1630 
1631   t1->syn = 0;
1632   t1->urg = 0;
1633   t1->fin = 0;
1634   t1->psh = 0;
1635   t1->doff = sizeof(*t1)/4;
1636   tcp_send_check(t1, saddr, daddr, sizeof(*t1), NULL);
1637   prot->queue_xmit(NULL, dev, buff, 1);
1638 }
1639 
1640 
1641 /*
1642  *      Look for tcp options. Parses everything but only knows about MSS.
1643  *      This routine is always called with the packet containing the SYN.
1644  *      However it may also be called with the ack to the SYN.  So you
1645  *      can't assume this is always the SYN.  It's always called after
1646  *      we have set up sk->mtu to our own MTU.
1647  */
1648  
1649 static void
1650 tcp_options(struct sock *sk, struct tcphdr *th)
1651 {
1652   unsigned char *ptr;
1653   int length=(th->doff*4)-sizeof(struct tcphdr);
1654   int mss_seen = 0;
1655     
1656   ptr = (unsigned char *)(th + 1);
1657   
1658   while(length>0)
1659   {
1660         int opcode=*ptr++;
1661         int opsize=*ptr++;
1662         switch(opcode)
1663         {
1664                 case TCPOPT_EOL:
1665                         return;
1666                 case TCPOPT_NOP:
1667                         length-=2;
1668                         continue;
1669                 
1670                 default:
1671                         if(opsize<=2)   /* Avoid silly options looping forever */
1672                                 return;
1673                         switch(opcode)
1674                         {
1675                                 case TCPOPT_MSS:
1676                                         if(opsize==4 && th->syn)
1677                                         {
1678                                                 sk->mtu=min(sk->mtu,ntohs(*(unsigned short *)ptr));
1679                                                 mss_seen = 1;
1680                                         }
1681                                         break;
1682                                 /* Add other options here as people feel the urge to implement stuff like large windows */
1683                         }
1684                         ptr+=opsize-2;
1685                         length-=opsize;
1686         }
1687   }
1688   if (th->syn) {
1689     if (! mss_seen)
1690       sk->mtu=min(sk->mtu, 536);  /* default MSS if none sent */
1691   }
1692   sk->mss = min(sk->max_window, sk->mtu);
1693 }
1694 
1695 static inline unsigned long default_mask(unsigned long dst)
1696 {
1697         dst = ntohl(dst);
1698         if (IN_CLASSA(dst))
1699                 return htonl(IN_CLASSA_NET);
1700         if (IN_CLASSB(dst))
1701                 return h

⌨️ 快捷键说明

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