ip.c

来自「mcf5307实验源代码」· C语言 代码 · 共 827 行 · 第 1/3 页

C
827
字号
        if (p->i.protocol == PROTUDP)
        {
            /* If the destination is either of the broadcast addresses, then
               pass it up to UDP.
            */
            if (comparen(p->i.ipdest, (void *)nullip, 4) ||
                comparen(p->i.ipdest, (void *)broadip, 4))
            {
                return (udpinterpret ((UDPKT *)p, iplen));
            }

            /*  Compare the incoming packet with our subnet mask.  If we are
                on the same net then check if this is a UDP packet.  If it is
                then call udpinterpret.  */
            our_net = 1;
            for(i=3; i>=0; i--)
                if((nnmask[i] & p->i.ipdest[i])!=(nnmask[i] & nnipnum[i]))
                    our_net = 0;
            if (our_net)
            {
                return (udpinterpret ((UDPKT *)p, iplen));
            }

            /* Finally, check to see if we have an IP address.  If not this is
               likely a BOOTP response that will provide us with one. */
            if (comparen(nnipnum, (void *)nullip, 4))
            {
                return (udpinterpret ((UDPKT *)p, iplen));
            }

        }

        /* SGJ, should log an error here. */
        /* Drop the packet by placing it back on the buffer_freelist. */
        dll_update_lists(&buffer_list, &buffer_freelist);

        /* Increment the number of IP packets received with the wrong IP addr. */
        SNMP_ipInAddrErrors_Inc;

        return (1);              /* drop packet */
	} /* end if */

	/* which protocol to handle this packet? */
    switch (p->i.protocol)
	{
        case PROTUDP:
            /* Increment the number of IP packets successfully delivered. */
            SNMP_ipInDelivers_Inc;

            return (udpinterpret((UDPKT *)p, iplen));

		case PROTTCP:
            /* Increment the number of IP packets successfully delivered. */
            SNMP_ipInDelivers_Inc;

            /* pass tcplen on to TCP */
            return (TCP_Interpret((TCPKT *)p, iplen));

		case PROTICMP:

            /* Increment the number of IP packets successfully delivered. */
            SNMP_ipInDelivers_Inc;

            return (icmpinterpret((ICMPKT *)p, iplen));

		default:
            NU_Tcp_Log_Error (TCP_IP_HIGH_LAYER, TCP_RECOVERABLE,
                              __FILE__, __LINE__);

            /* Drop the packet by placing it back on the buffer_freelist. */
            dll_update_lists(&buffer_list, &buffer_freelist);

            /* Increment the number of IP packets received with a invalid
               protocol field. */
            SNMP_ipInUnknownProtos_Inc;

            return (1);
	}  /* end switch */
} /* end ipinterpret */

/******************************************************************************/
/*                                                                            */
/* FUNCTION                                                                   */
/*                                                                            */
/*      icmpinterpret                                                         */
/*                                                                            */
/* DESCRIPTION                                                                */
/*                                                                            */
/*  Interpret the icmp message that just came off the wire                    */
/*                                                                            */
/* CALLED BY                                                                  */
/*      ipinterpret                                                           */
/*                                                                            */
/* CALLS                                                                      */
/*                                                                            */
/*      ipcheck                                                               */
/*      neticmpturn                                                           */
/*      netputevent                                                           */
/*      dll_update_lists                                                      */
/*                                                                            */
/******************************************************************************/
static int16 icmpinterpret (ICMPKT *p, uint16 icmplen)
{
    uint16 i;
    IPLAYER *iptr;

    /* Increment the total number of ICMP messages received. */
    SNMP_icmpInMsgs_Inc;

    i = p->c.type;

    if (p->c.check)
    {        /* ignore if chksum=0 */
        if (ipchecklen ((int8 *)&p->c, (uint16)(icmplen >> 1)))
        {
			NU_Tcp_Log_Error (TCP_ICMP_CKSUM, TCP_RECOVERABLE,
							  __FILE__, __LINE__);

            /* Drop the packet by placing it back on the buffer_freelist. */
            dll_update_lists(&buffer_list, &buffer_freelist);

            /* Increment the number of ICMP messages received with errors. */
            SNMP_icmpInErrors_Inc;

            return (-1);
        } /* end if */
    } /* end if */

    switch(i)
    {
        case 8:                         /* ping request sent to me */

             /* Increment the number of Echo requests received. */
             SNMP_icmpInEchos_Inc;

             p->c.type = 0;                /* echo reply type */

             /* Increment the number of Echo replies sent. */
             SNMP_icmpOutEchoReps_Inc;

             neticmpturn (p, icmplen);     /* send back */

             break;

        case 5:                         /* ICMP redirect */
             iptr = (IPLAYER *)p->data;
			 netputevent (ICMPCLASS, IREDIR, 0);	  /* event to be picked up */
             memcpy ((void *)nnicmpnew, (const void *)&p->c.part1, 4);         /* new gateway */
             memcpy ((void *)nnicmpsave, (const void *)iptr->ipdest, 4);       /* dest address */

             /* Increment the number of Redirect messages received. */
             SNMP_icmpInRedirects_Inc;

             break;

        case 4:                         /* ICMP source quench */
             OKpackets = 0;
             SQwait += 100;

             /* Increment the number of Source Quench messages received. */
             SNMP_icmpInSrcQuenchs_Inc;

             break;

        default:

            /* Increment the number of ICMP messages received with errors. */
            SNMP_icmpInErrors_Inc;
            break;

    } /* end switch */

    /* Drop the packet by placing it back on the buffer_freelist. */
    dll_update_lists(&buffer_list, &buffer_freelist);
    return (0);
}   /* end icmpinterpret() */

/******************************************************************************/
/*                                                                            */
/* FUNCTION                                                                   */
/*                                                                            */
/*      neticmpturn                                                           */
/*                                                                            */
/* DESCRIPTION                                                                */
/*                                                                            */
/*   send out an icmp packet, probably in response to a ping operation        */
/*   interchanges the source and destination addresses of the packet,         */
/*   puts in my addresses for the source and sends it                         */
/*                                                                            */
/*   does not change any of the ICMP fields, just the IP and dlayers          */
/*   returns 0 on okay send, nonzero on error                                 */
/*                                                                            */
/* CALLED BY                                                                  */
/*      icmpinterpret                                                         */
/*                                                                            */
/* CALLS                                                                      */
/*                                                                            */
/*      intswap                                                               */
/*      ipcheck                                                               */
/*                                                                            */
/*  NAME             DATE     REMARKS                                         */
/*                                                                            */
/*  Glen Johnson   05/01/96   Fixed a bug in the transmission of the ICMP     */
/*                            packet.                                         */
/*                                                                            */
/******************************************************************************/
static int16 neticmpturn (ICMPKT *p, uint16 ilen)
{
    ICMPKT *icmp_pkt;
    struct pqueue HUGE *buf_ptr;

    if (comparen (p->d.me, (VOID *)broadaddr, DADDLEN))
        return(0);

     /* Allocate a buffer to place the packet in. */
     buf_ptr = (struct pqueue HUGE *)dll_dequeue((tqe_t *)&buffer_freelist);

     if(buf_ptr == NU_NULL)
         return (NU_NO_BUFFERS);

    /* Overlay the packet so that individual fields can be accessed. */
    icmp_pkt = (ICMPKT *)buf_ptr->packet;

    /* Copy the received packet into the outgoing packet.  The received packet
       can be used almost as is.  Only a few fields need to be swapped. */
    memcpy (icmp_pkt, p, sizeof (DLAYER) + sizeof (IPLAYER) + ilen);

    /* Swap the destination and source addresses. */
    memcpy ((void *)icmp_pkt->d.dest, (const void *)icmp_pkt->d.me,
             DADDLEN);
    memcpy ((void *)icmp_pkt->i.ipdest, (const void *)icmp_pkt->i.ipsource,
             4);
    memcpy ((void *)icmp_pkt->d.me, (const void *)nnmyaddr, DADDLEN);
    memcpy ((void *)icmp_pkt->i.ipsource, (const void *)nnipnum, 4);

    /* Prepare ICMP checksum */
    icmp_pkt->c.check = 0;
    icmp_pkt->c.check = ipchecklen ((int8 *) &icmp_pkt->c, 
									(uint16)(ilen >> 1));

    /* Prepare iplayer for send */
    icmp_pkt->i.ident = intswap ((uint16)nnipident++);
    icmp_pkt->i.check = 0;
    icmp_pkt->i.check = ipchecklen ((int8 *) &icmp_pkt->i, 10);

    /* Increment the number of IP packets transmitted. */
    SNMP_ipOutRequests_Inc;

    /* Increment the number of ICMP messages sent. */
    SNMP_icmpOutMsgs_Inc;

    /* Send the packet. */
    return (NET_Send(buf_ptr, (int16)(sizeof(DLAYER) + sizeof(IPLAYER) + ilen),
                     OTHER_PKT));

}  /* end neticmpturn */


#ifdef IP_FRAG
/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      ip_reassembly                                                    */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*  This function takes an IP fragment, checks to see if other fragments */
/*  from the same packet has arrived, and then calls the appropriate     */
/*  routine to handle the fragment.                                      */
/*                                                                       */
/* CALLED BY                                                             */
/*      ipinterpret                                                      */
/*                                                                       */
/* CALLS                                                                 */
/*      first_frag                                                       */

⌨️ 快捷键说明

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