udp.c

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

C
467
字号
/*                                                                       */
/*  Get the data from the UDP buffer and transfer it into your buffer.   */
/*  Returns the number of bytes transferred or -1 of none available.     */
/*                                                                       */
/* CALLED BY                                                             */
/*      bootp                                                            */
/*      NU_Recv_From                                                     */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*                                                                       */
/*************************************************************************/
int16 neturead (struct uport *uptr, char *buffer, struct addr_struct *from,
              struct sock_struct *sockptr)
{
    UDPKT *pkt_ptr;
    int16 datalen;

    /* Check to see if there are any packets waiting. */
    if (uptr->dgram_list.head == NU_NULL)
        return (NU_NO_DATA_TRANSFER);

#ifndef POINT_TO_POINT
    /* Set up a pointer to the packet stored in first buffer in the list */
    pkt_ptr = (UDPKT *)uptr->dgram_list.head->packet;
#else
#ifdef NU_PPP
    /* Set up a pointer to the packet stored in first buffer in the list */
    pkt_ptr = (UDPKT *)(uptr->dgram_list.head->data_ptr - sizeof(UDPLAYER) - sizeof(DLAYER) - sizeof(IPLAYER));
#else
    /* Set up a pointer to the packet stored in first buffer in the list */
    pkt_ptr = (UDPKT *)(uptr->dgram_list.head->packet - sizeof (DLAYER));
#endif
#endif


    /* Move the data into the caller's buffer. */
    memcpy ((void *)buffer, (const void *)pkt_ptr->data,
             uptr->dgram_list.head->data_len);

    /*  Get his IP number.  */
    memcpy (&(from->id), pkt_ptr->i.ipsource, 4);

    /*  Get his port number. */
    from->port = (int16)intswap(pkt_ptr->u.source);

    /*  Update the socket descriptor with foreign address
        information.  */
    memcpy (&(sockptr->foreign_addr.ip_num), pkt_ptr->i.ipsource, 4);
    sockptr->foreign_addr.port_num = (int16)intswap(pkt_ptr->u.source);

    /* Preserve the amount of data that was copied so that it can be returned
       below. */
    datalen = uptr->dgram_list.head->data_len;

    /* Place this buffer back onto the free list. */
    dll_update_lists(&uptr->dgram_list, &buffer_freelist);

    /* Update the number of buffered datagrams. */
    uptr->in_dgrams--;

    return (datalen);
}
/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      netulisten (int16)                                               */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*  Specify which UDP port number to listen to -- can only listen to     */
/*  one port at a time.                                                  */
/*                                                                       */
/* CALLED BY                                                             */
/*      bootp                                                            */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*                                                                       */
/*************************************************************************/
void netulisten(int16 port)
{
      ulist.listen = (uint16)port;
}

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      netusend (struct uport *, uint8 *, int16)                        */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*  Send some data out in a udp packet ( uses the preinitialized data    */
/*  in the port packet *ulist.udpout* )                                  */
/*                                                                       */
/*  Returns 0 on ok send, non-zero for an error                          */
/*                                                                       */
/* CALLED BY                                                             */
/*      sendbootp                                                        */
/*      senddom                                                          */
/*      NU_Send_To                                                       */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      intswap                                                          */
/*      NET_Send                                                         */
/*      netdlayer                                                        */
/*      tcpcheck                                                         */
/*      ipcheck                                                          */
/*                                                                       */
/*************************************************************************/
int16 netusend (struct uport *uptr, uint8 *buffer, uint16 nbytes,
                uint16 sock_options)
{
    struct acache      *pc;
    UDPKT              *udp_pkt;
    struct pqueue HUGE *buf_ptr;

    /*  Don't send more than we have concluded is our maximum.  */
    if (nbytes > UMAXLEN)
        nbytes = UMAXLEN;

     /* 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);
     }

     udp_pkt = (UDPKT *)buf_ptr->packet;


     memcpy ((void *)udp_pkt, (const void *)&uptr->out,
              sizeof(DLAYER) + sizeof(IPLAYER) + sizeof(UDPLAYER));

    /*  Make sure that we have the right dlayer address.  */
    /*  If we wish to broadcast then simply copy the dlayer broadcast
     *  address to the destination.  Else we need to look up the
     *  dlayer address.
     */
    if (memcmp(uptr->out.i.ipdest, (void *)broadip, 4) == 0)
    {
        if ((sock_options & SO_BROADCAST) == 0)
        {
            dll_enqueue((tqe_t *)&buffer_freelist, (tqe_t *)buf_ptr);
            return (NU_ACCES);
        }

        /*  Copy the dlayer broadcast address  */
        memcpy ((void *)udp_pkt->d.dest, (const void *)broadaddr,
                 DADDLEN);
    }
    else
    {
#ifndef POINT_TO_POINT
        pc = (struct acache *)netdlayer (uptr->out.i.ipdest);
        if (pc == NU_NULL)
        {
            /* Increment the number of packets that could not be delivered. */
            SNMP_ipOutNoRoutes_Inc;

            dll_enqueue((tqe_t *)&buffer_freelist, (tqe_t *)buf_ptr);

            return (-2);
        }

        /*  Pick up his physical address  */
        memcpy ((void *)udp_pkt->d.dest, (const void *)pc->hrd,
                 DADDLEN);
#endif
    }

    /*  Set up the checksum header.  */
    memcpy ((void *)uptr->tcps.source, (const void *)nnipnum, 4);
    memcpy ((void *)uptr->tcps.dest, (const void *)uptr->out.i.ipdest,
             4);
    uptr->tcps.tcplen = intswap ((uint16)(nbytes + sizeof (UDPLAYER)));

    /*  Set up the UDP header. */

    /*  Get the length of the buffer.  */
    udp_pkt->u.length = intswap ((uint16)(nbytes + sizeof (UDPLAYER)));

    /*  Move the data into the output buffer.  */
    memcpy  ((void *)udp_pkt->data, (const void *)buffer, nbytes);

    /*  Calculate the checksum. */
    udp_pkt->u.check = tcpcheck ((uint16 *) &uptr->tcps,
                                  (uint16 *) &uptr->out.u,
                                  (uint16)(nbytes + sizeof(UDPLAYER)));

    /*********************  DANGER DANGER **********************/
    /*                                                         */
    /*    THIS NEXT STATEMENT IS BECAUSE THE CHECKSUM IS NOT   */
    /*    WORKING.                                             */
    /*                                                         */
    /*********************  DANGER DANGER **********************/
    udp_pkt->u.check = 0;

    /*  Set up the IP header information.  */

    /*  Set up the protocol type.  */
    udp_pkt->i.protocol = PROTUDP;

    /*  Get IP header length.  */
    udp_pkt->i.tlen = intswap ((uint16)(nbytes + sizeof (IPLAYER) + 
                                  sizeof (UDPLAYER)));

    /*  Get the IP identifier.  */
    udp_pkt->i.ident = intswap ((uint16)nnipident++);

    /*  Calculate the checksum for the IP header.  */
    udp_pkt->i.check = 0;
    udp_pkt->i.check = ipcheck ((uint16 *) &udp_pkt->i, 10);

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

    /* Increment the number of UDP datagrams transmitted. */
    SNMP_udpoutDatagrams_Inc;

    /* Send the packet. */
    NET_Send(buf_ptr, (uint16)(nbytes + sizeof(DLAYER) + sizeof(IPLAYER) +
             sizeof(UDPLAYER)), OTHER_PKT);

    /*  If the send went ok, then return the number of bytes sent. */
    return((int16)nbytes);

}  /* end netusend */

⌨️ 快捷键说明

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