# /* udp_read.c */ /* EMACS_MODES: c !fill */ /* User Datagram Protocol layer for the UNIX network system. The * following routines are included: * udp_read receive a udp packet */ #include udp_read (fd, buf, len) /* Read the next available udp packet from the net into the specified * buffer of length len. Return the length of the received packet in * bytes. If no packet is available returns 0. * The macro udp_data() may be used to obtain a pointer to the start * of the data area of the packet. * * Arguments: */ int fd; /* file descriptor */ caddr_t buf; /* receive buffer */ int len; /* length of receive buffer */ { struct udpph ph; /* pseudo-header */ reg struct udp *pup; /* upd packet ptr. */ reg struct ip *pip; /* ip packet ptr */ int datalen; /* len. of rcvd. packet */ int inlen; /* len. of in packet */ int udplen; /* len. of udp packet */ unshort csum; /* temp. checksum */ caddr_t pdata; /* ptr. to data part of packet */ if ((datalen = in_read (fd, buf, len)) == 0) return (0); pip = in_head(buf); /* get in & udp headers */ pup = in_data(pip); inlen = pip->ip_len; /* get in len */ udplen = short_to_net(pup->ud_len); /* and udp len */ if (udplen < sizeof (struct udp) || inlen > datalen || (udplen + (pip->ip_ihl << 2)) != inlen) /* bad length? */ return (0); /* yes, punt */ if (udplen & 1) { /* if a goddam odd byte count */ pdata = (char *)(pup); /* must zero-pad to even count */ pdata[udplen] = 0; } ph.ph_src = pip->ip_src; /* build pseudo-header */ ph.ph_dest = pip->ip_dest; ph.ph_zero = 0; ph.ph_prot = pip->ip_prot; ph.ph_len = pup->ud_len; csum = pup->ud_cksum; /* check the checksum */ if (csum != 0) { /* goddam checksums may be unused! */ pup->ud_cksum = cksum (&ph, sizeof (ph) >> 1, 0); if (udplen > BIGCKSUM) /* see if fast cksum routine better */ pup->ud_cksum = ~fcksum (pup, (udplen + 1) >> 1, 0); else pup->ud_cksum = ~cksum (pup, (udplen + 1) >> 1, 0); if (pup->ud_cksum != csum) return (0); } #ifndef BIGINDIAN udpswab (pup); /* swap bytes if needed */ #endif return (datalen); }