V10/lsys/inet/udp_input.c
/* udp_input.c 6.1 83/07/29 */
#include "sys/param.h"
#include "sys/stream.h"
#include "sys/inet/in.h"
#include "sys/inet/ip.h"
#include "sys/inet/ip_var.h"
#include "sys/inet/udp.h"
#include "sys/inet/udp_var.h"
int udpcksum = 0;
/*
* UDP input routine
*/
udp_input(bp)
struct block *bp;
{
register struct udpiphdr *ui;
register struct block *head;
int len, ulen;
/*
* Get IP and UDP header together in first block.
* Note: IP leaves IP header in first block.
*/
ui = (struct udpiphdr *)bp->rptr;
/*
* must strip options so udpiphdr is in the right place
*/
if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2))
ip_stripoptions(bp, (struct block *)0);
if (BLEN(bp) < sizeof (struct udpiphdr)) {
if ((bp = bp_pullup(bp, sizeof (struct udpiphdr))) == 0) {
udpstat.udps_hdrops++;
return;
}
ui = (struct udpiphdr *)bp->rptr;
}
/*
* Checksum extended UDP header and data.
*/
ulen = ((struct ip *)ui)->ip_len;
len = sizeof (struct ip) + ulen;
ui->ui_src = htonl(ui->ui_src);
ui->ui_dst = htonl(ui->ui_dst);
if (udpcksum) {
ui->ui_next = 0;
ui->ui_x1 = 0;
ui->ui_len = htons((u_short)ulen);
if (ui->ui_sum = in_cksum(bp, len)) {
printf("udp_cksum: sum %x len %d src %x\n", ui->ui_sum,
len, ui->ui_src);
udpstat.udps_badsum++;
bp_free(bp);
return;
}
}
udpstat.udps_ipackets++;
/*
* Drop UDP and IP headers.
*/
bp->rptr += sizeof(struct udpiphdr);
/*
* adjust size to reflect length
* find end of queue and adjust wptr accordingly
*/
head = bp;
len = 0;
/*
* ulen is length of udphdr+data. since we've already shortened first buffer
* by sizeof(udpiphdr), shorten ulen by sizeof(udphdr)
*/
ulen -= sizeof(struct udphdr);
while(bp) {
len += bp->wptr - bp->rptr;
if (len > ulen) {
bp->wptr -= len-ulen;
bp_free(bp->next);
bp->next = 0;
}
bp = bp->next;
}
/*
* Convert UDP protocol specific fields to host format.
*/
ui->ui_src = ntohl(ui->ui_src);
ui->ui_dst = ntohl(ui->ui_dst);
ui->ui_sport = ntohs(ui->ui_sport);
ui->ui_dport = ntohs(ui->ui_dport);
udpdrint(head, ui);
}