version 1.75, 2001/01/24 09:04:16 |
version 1.75.2.1, 2001/06/21 20:08:46 |
|
|
* @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 |
* @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 |
*/ |
*/ |
|
|
|
#include "opt_inet.h" |
#include "opt_ipsec.h" |
#include "opt_ipsec.h" |
|
#include "opt_inet_csum.h" |
#include "opt_ipkdb.h" |
#include "opt_ipkdb.h" |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
|
|
#endif |
#endif |
#endif |
#endif |
|
|
|
#include "faith.h" |
|
#if defined(NFAITH) && NFAITH > 0 |
|
#include <net/if_faith.h> |
|
#endif |
|
|
#include <machine/stdarg.h> |
#include <machine/stdarg.h> |
|
|
#ifdef IPSEC |
#ifdef IPSEC |
Line 154 static void udp_notify __P((struct inpcb |
|
Line 161 static void udp_notify __P((struct inpcb |
|
#endif |
#endif |
int udbhashsize = UDBHASHSIZE; |
int udbhashsize = UDBHASHSIZE; |
|
|
|
#ifdef UDP_CSUM_COUNTERS |
|
#include <sys/device.h> |
|
|
|
struct evcnt udp_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
|
NULL, "udp", "hwcsum bad"); |
|
struct evcnt udp_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
|
NULL, "udp", "hwcsum ok"); |
|
struct evcnt udp_hwcsum_data = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
|
NULL, "udp", "hwcsum data"); |
|
struct evcnt udp_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
|
NULL, "udp", "swcsum"); |
|
|
|
#define UDP_CSUM_COUNTER_INCR(ev) (ev)->ev_count++ |
|
|
|
#else |
|
|
|
#define UDP_CSUM_COUNTER_INCR(ev) /* nothing */ |
|
|
|
#endif /* UDP_CSUM_COUNTERS */ |
|
|
void |
void |
udp_init() |
udp_init() |
{ |
{ |
|
|
#ifdef INET |
#ifdef INET |
in_pcbinit(&udbtable, udbhashsize, udbhashsize); |
in_pcbinit(&udbtable, udbhashsize, udbhashsize); |
#endif |
#endif |
|
|
|
#ifdef UDP_CSUM_COUNTERS |
|
evcnt_attach_static(&udp_hwcsum_bad); |
|
evcnt_attach_static(&udp_hwcsum_ok); |
|
evcnt_attach_static(&udp_hwcsum_data); |
|
evcnt_attach_static(&udp_swcsum); |
|
#endif /* UDP_CSUM_COUNTERS */ |
} |
} |
|
|
#ifndef UDP6 |
#ifndef UDP6 |
Line 249 udp_input(m, va_alist) |
|
Line 283 udp_input(m, va_alist) |
|
* Checksum extended UDP header and data. |
* Checksum extended UDP header and data. |
*/ |
*/ |
if (uh->uh_sum) { |
if (uh->uh_sum) { |
if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0) { |
switch (m->m_pkthdr.csum_flags & |
udpstat.udps_badsum++; |
((m->m_pkthdr.rcvif->if_csum_flags & M_CSUM_UDPv4) | |
m_freem(m); |
M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) { |
return; |
case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD: |
|
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad); |
|
goto badcsum; |
|
|
|
case M_CSUM_UDPv4|M_CSUM_DATA: |
|
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_data); |
|
if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) |
|
goto badcsum; |
|
break; |
|
|
|
case M_CSUM_UDPv4: |
|
/* Checksum was okay. */ |
|
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_ok); |
|
break; |
|
|
|
default: |
|
/* Need to compute it ourselves. */ |
|
UDP_CSUM_COUNTER_INCR(&udp_swcsum); |
|
if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0) |
|
goto badcsum; |
|
break; |
} |
} |
} |
} |
|
|
Line 316 udp_input(m, va_alist) |
|
Line 370 udp_input(m, va_alist) |
|
bad: |
bad: |
if (m) |
if (m) |
m_freem(m); |
m_freem(m); |
|
return; |
|
|
|
badcsum: |
|
m_freem(m); |
|
udpstat.udps_badsum++; |
} |
} |
#endif |
#endif |
|
|
Line 332 udp6_input(mp, offp, proto) |
|
Line 391 udp6_input(mp, offp, proto) |
|
struct udphdr *uh; |
struct udphdr *uh; |
u_int32_t plen, ulen; |
u_int32_t plen, ulen; |
|
|
|
#ifndef PULLDOWN_TEST |
|
IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); |
|
#endif |
|
ip6 = mtod(m, struct ip6_hdr *); |
|
|
#if defined(NFAITH) && 0 < NFAITH |
#if defined(NFAITH) && 0 < NFAITH |
if (m->m_pkthdr.rcvif) { |
if (faithprefix(&ip6->ip6_dst)) { |
if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { |
/* send icmp6 host unreach? */ |
/* send icmp6 host unreach? */ |
m_freem(m); |
m_freem(m); |
return IPPROTO_DONE; |
return IPPROTO_DONE; |
|
} |
|
} |
} |
#endif |
#endif |
|
|
udp6stat.udp6s_ipackets++; |
udp6stat.udp6s_ipackets++; |
|
|
#ifndef PULLDOWN_TEST |
|
IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); |
|
#endif |
|
|
|
ip6 = mtod(m, struct ip6_hdr *); |
|
/* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ |
/* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ |
plen = m->m_pkthdr.len - off; |
plen = m->m_pkthdr.len - off; |
#ifndef PULLDOWN_TEST |
#ifndef PULLDOWN_TEST |
Line 942 udp_input(m, va_alist) |
|
Line 999 udp_input(m, va_alist) |
|
* Checksum extended UDP header and data. |
* Checksum extended UDP header and data. |
*/ |
*/ |
if (uh->uh_sum) { |
if (uh->uh_sum) { |
bzero(((struct ipovly *)ip)->ih_x1, |
switch (m->m_pkthdr.csum_flags & |
sizeof ((struct ipovly *)ip)->ih_x1); |
((m->m_pkthdr.rcvif->if_csum_flags & M_CSUM_UDPv4) | |
((struct ipovly *)ip)->ih_len = uh->uh_ulen; |
M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) { |
if (in_cksum(m, len + sizeof (struct ip)) != 0) { |
case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD: |
udpstat.udps_badsum++; |
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad); |
m_freem(m); |
goto badcsum; |
return; |
|
|
case M_CSUM_UDPv4|M_CSUM_DATA: |
|
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_data); |
|
if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) |
|
goto badcsum; |
|
break; |
|
|
|
case M_CSUM_UDPv4: |
|
/* Checksum was okay. */ |
|
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_ok); |
|
break; |
|
|
|
default: |
|
/* Need to compute it ourselves. */ |
|
UDP_CSUM_COUNTER_INCR(&udp_swcsum); |
|
bzero(((struct ipovly *)ip)->ih_x1, |
|
sizeof ((struct ipovly *)ip)->ih_x1); |
|
((struct ipovly *)ip)->ih_len = uh->uh_ulen; |
|
if (in_cksum(m, len + sizeof (struct ip)) != 0) |
|
goto badcsum; |
|
break; |
} |
} |
} |
} |
|
|
|
|
m_freem(m); |
m_freem(m); |
if (opts) |
if (opts) |
m_freem(opts); |
m_freem(opts); |
|
return; |
|
|
|
badcsum: |
|
udpstat.udps_badsum++; |
|
m_freem(m); |
} |
} |
#endif /*UDP6*/ |
#endif /*UDP6*/ |
|
|
Line 1233 udp_output(m, va_alist) |
|
Line 1315 udp_output(m, va_alist) |
|
* and addresses and length put into network format. |
* and addresses and length put into network format. |
*/ |
*/ |
ui = mtod(m, struct udpiphdr *); |
ui = mtod(m, struct udpiphdr *); |
bzero(ui->ui_x1, sizeof ui->ui_x1); |
|
ui->ui_pr = IPPROTO_UDP; |
ui->ui_pr = IPPROTO_UDP; |
ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr)); |
|
ui->ui_src = inp->inp_laddr; |
ui->ui_src = inp->inp_laddr; |
ui->ui_dst = inp->inp_faddr; |
ui->ui_dst = inp->inp_faddr; |
ui->ui_sport = inp->inp_lport; |
ui->ui_sport = inp->inp_lport; |
ui->ui_dport = inp->inp_fport; |
ui->ui_dport = inp->inp_fport; |
ui->ui_ulen = ui->ui_len; |
ui->ui_ulen = htons((u_int16_t)len + sizeof(struct udphdr)); |
|
|
/* |
/* |
* Stuff checksum and output datagram. |
* Set up checksum and output datagram. |
*/ |
*/ |
ui->ui_sum = 0; |
|
if (udpcksum) { |
if (udpcksum) { |
if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) |
/* |
ui->ui_sum = 0xffff; |
* XXX Cache pseudo-header checksum part for |
} |
* XXX "connected" UDP sockets. |
|
*/ |
|
ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr, |
|
ui->ui_dst.s_addr, htons((u_int16_t)len + |
|
sizeof(struct udphdr) + IPPROTO_UDP)); |
|
m->m_pkthdr.csum_flags = M_CSUM_UDPv4; |
|
m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); |
|
} else |
|
ui->ui_sum = 0; |
((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; |
((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; |
((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ |
((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ |
((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ |
((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ |