Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet/udp_usrreq.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet/udp_usrreq.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.146.2.1 retrieving revision 1.167 diff -u -p -r1.146.2.1 -r1.167 --- src/sys/netinet/udp_usrreq.c 2006/02/05 03:09:11 1.146.2.1 +++ src/sys/netinet/udp_usrreq.c 2008/04/15 03:57:04 1.167 @@ -1,4 +1,4 @@ -/* $NetBSD: udp_usrreq.c,v 1.146.2.1 2006/02/05 03:09:11 rpaulo Exp $ */ +/* $NetBSD: udp_usrreq.c,v 1.167 2008/04/15 03:57:04 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.146.2.1 2006/02/05 03:09:11 rpaulo Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.167 2008/04/15 03:57:04 thorpej Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -94,16 +94,14 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c #include #include #include - -#ifdef IPSEC_NAT_T -#include -#include -#endif +#include #ifdef INET6 #include #include #include +#include +#include #include #include #endif @@ -123,6 +121,7 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c #ifdef FAST_IPSEC #include #include /* XXX ipsecstat namespace */ +#include #ifdef INET6 #include #endif @@ -130,6 +129,7 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c #ifdef IPSEC #include +#include #include #endif /*IPSEC*/ @@ -141,15 +141,12 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c * UDP protocol implementation. * Per RFC 768, August, 1980. */ -#ifndef COMPAT_42 int udpcksum = 1; -#else -int udpcksum = 0; /* XXX */ -#endif int udp_do_loopback_cksum = 0; struct inpcbtable udbtable; -struct udpstat udpstat; + +percpu_t *udpstat_percpu; #ifdef INET #ifdef IPSEC_NAT_T @@ -179,9 +176,9 @@ static void udp_notify (struct inpcb *, int udbhashsize = UDBHASHSIZE; #ifdef MBUFTRACE -struct mowner udp_mowner = { "udp" }; -struct mowner udp_rx_mowner = { "udp", "rx" }; -struct mowner udp_tx_mowner = { "udp", "tx" }; +struct mowner udp_mowner = MOWNER_INIT("udp", ""); +struct mowner udp_rx_mowner = MOWNER_INIT("udp", "rx"); +struct mowner udp_tx_mowner = MOWNER_INIT("udp", "tx"); #endif #ifdef UDP_CSUM_COUNTERS @@ -236,6 +233,8 @@ udp_init(void) MOWNER_ATTACH(&udp_tx_mowner); MOWNER_ATTACH(&udp_rx_mowner); MOWNER_ATTACH(&udp_mowner); + + udpstat_percpu = percpu_alloc(sizeof(uint64_t) * UDP_NSTATS); } /* @@ -330,7 +329,7 @@ udp4_input_checksum(struct mbuf *m, cons return 0; badcsum: - udpstat.udps_badsum++; + UDP_STATINC(UDP_STAT_BADSUM); return -1; } @@ -352,7 +351,7 @@ udp_input(struct mbuf *m, ...) va_end(ap); MCLAIM(m, &udp_rx_mowner); - udpstat.udps_ipackets++; + UDP_STATINC(UDP_STAT_IPACKETS); /* * Get IP and UDP header together in first mbuf. @@ -360,7 +359,7 @@ udp_input(struct mbuf *m, ...) ip = mtod(m, struct ip *); IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr)); if (uh == NULL) { - udpstat.udps_hdrops++; + UDP_STATINC(UDP_STAT_HDROPS); return; } KASSERT(UDP_HDR_ALIGNED_P(uh)); @@ -377,7 +376,7 @@ udp_input(struct mbuf *m, ...) len = ntohs((u_int16_t)uh->uh_ulen); if (ip_len != iphlen + len) { if (ip_len < iphlen + len || len < sizeof(struct udphdr)) { - udpstat.udps_badlen++; + UDP_STATINC(UDP_STAT_BADLEN); goto bad; } m_adj(m, iphlen + len - ip_len); @@ -390,19 +389,11 @@ udp_input(struct mbuf *m, ...) goto badcsum; /* construct source and dst sockaddrs. */ - bzero(&src, sizeof(src)); - src.sin_family = AF_INET; - src.sin_len = sizeof(struct sockaddr_in); - bcopy(&ip->ip_src, &src.sin_addr, sizeof(src.sin_addr)); - src.sin_port = uh->uh_sport; - bzero(&dst, sizeof(dst)); - dst.sin_family = AF_INET; - dst.sin_len = sizeof(struct sockaddr_in); - bcopy(&ip->ip_dst, &dst.sin_addr, sizeof(dst.sin_addr)); - dst.sin_port = uh->uh_dport; + sockaddr_in_init(&src, &ip->ip_src, uh->uh_sport); + sockaddr_in_init(&dst, &ip->ip_dst, uh->uh_dport); if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) { - udpstat.udps_hdrops++; + UDP_STATINC(UDP_STAT_HDROPS); return; } #ifdef INET6 @@ -430,10 +421,10 @@ udp_input(struct mbuf *m, ...) if (n == 0) { if (m->m_flags & (M_BCAST | M_MCAST)) { - udpstat.udps_noportbcast++; + UDP_STATINC(UDP_STAT_NOPORTBCAST); goto bad; } - udpstat.udps_noport++; + UDP_STATINC(UDP_STAT_NOPORT); #ifdef IPKDB if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport, m, iphlen + sizeof(struct udphdr), @@ -538,7 +529,7 @@ udp6_input(struct mbuf **mp, int *offp, plen = m->m_pkthdr.len - off; IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr)); if (uh == NULL) { - ip6stat.ip6s_tooshort++; + IP6_STATINC(IP6_STAT_TOOSHORT); return IPPROTO_DONE; } KASSERT(UDP_HDR_ALIGNED_P(uh)); @@ -631,14 +622,14 @@ udp4_sendup(struct mbuf *m, int off /* o /* check AH/ESP integrity. */ if (so != NULL && ipsec4_in_reject_so(m, so)) { ipsecstat.in_polvio++; - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) + if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) icmp_error(n, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT, 0, 0); return; } #endif /*IPSEC*/ - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) { if (inp && (inp->inp_flags & INP_CONTROLOPTS || so->so_options & SO_TIMESTAMP)) { struct ip *ip = mtod(n, struct ip *); @@ -652,7 +643,7 @@ udp4_sendup(struct mbuf *m, int off /* o if (opts) m_freem(opts); so->so_rcv.sb_overflowed++; - udpstat.udps_fullsock++; + UDP_STATINC(UDP_STAT_FULLSOCK); } else sorwakeup(so); } @@ -678,14 +669,14 @@ udp6_sendup(struct mbuf *m, int off /* o /* check AH/ESP integrity. */ if (so != NULL && ipsec6_in_reject_so(m, so)) { ipsec6stat.in_polvio++; - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) + if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) icmp6_error(n, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN, 0); return; } #endif /*IPSEC*/ - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) { if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS || in6p->in6p_socket->so_options & SO_TIMESTAMP)) { struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *); @@ -792,7 +783,7 @@ udp4_realinput(struct sockaddr_in *src, */ inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport); if (inp == 0) { - ++udpstat.udps_pcbhashmiss; + UDP_STATINC(UDP_STAT_PCBHASHMISS); inp = in_pcblookup_bind(&udbtable, *dst4, *dport); if (inp == 0) return rcvcnt; @@ -940,7 +931,7 @@ udp6_realinput(int af, struct sockaddr_i in6p = in6_pcblookup_connect(&udbtable, &src6, sport, dst6, dport, 0); if (in6p == 0) { - ++udpstat.udps_pcbhashmiss; + UDP_STATINC(UDP_STAT_PCBHASHMISS); in6p = in6_pcblookup_bind(&udbtable, dst6, dport, 0); if (in6p == 0) return rcvcnt; @@ -969,7 +960,7 @@ udp_notify(struct inpcb *inp, int errno) } void * -udp_ctlinput(int cmd, struct sockaddr *sa, void *v) +udp_ctlinput(int cmd, const struct sockaddr *sa, void *v) { struct ip *ip = v; struct udphdr *uh; @@ -989,23 +980,20 @@ udp_ctlinput(int cmd, struct sockaddr *s else if (errno == 0) return NULL; if (ip) { - uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); - in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport, + uh = (struct udphdr *)((char *)ip + (ip->ip_hl << 2)); + in_pcbnotify(&udbtable, satocsin(sa)->sin_addr, uh->uh_dport, ip->ip_src, uh->uh_sport, errno, notify); /* XXX mapped address case */ } else - in_pcbnotifyall(&udbtable, satosin(sa)->sin_addr, errno, + in_pcbnotifyall(&udbtable, satocsin(sa)->sin_addr, errno, notify); return NULL; } int -udp_ctloutput(op, so, level, optname, mp) - int op; - struct socket *so; - int level, optname; - struct mbuf **mp; +udp_ctloutput(int op, struct socket *so, int level, int optname, + struct mbuf **mp) { int s; int error = 0; @@ -1036,7 +1024,6 @@ udp_ctloutput(op, so, level, optname, mp default: error = EAFNOSUPPORT; goto end; - break; } @@ -1047,9 +1034,9 @@ udp_ctloutput(op, so, level, optname, mp switch (optname) { case UDP_ENCAP: - if (m == NULL || m->m_len < sizeof (int)) { + if (m == NULL || m->m_len != sizeof(int)) { error = EINVAL; - goto end; + break; } switch(*mtod(m, int *)) { @@ -1070,21 +1057,21 @@ udp_ctloutput(op, so, level, optname, mp #endif default: error = EINVAL; - goto end; break; } break; default: error = ENOPROTOOPT; - goto end; break; } + if (m != NULL) { + m_free(m); + } break; default: error = EINVAL; - goto end; break; } @@ -1160,7 +1147,7 @@ udp_output(struct mbuf *m, ...) ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len); ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ - udpstat.udps_opackets++; + UDP_STATINC(UDP_STAT_OPACKETS); return (ip_output(m, inp->inp_options, ro, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), @@ -1181,23 +1168,23 @@ udp_usrreq(struct socket *so, int req, s struct mbuf *control, struct lwp *l) { struct inpcb *inp; - struct proc *p; int s; int error = 0; - p = l ? l->l_proc : NULL; if (req == PRU_CONTROL) - return (in_control(so, (long)m, (caddr_t)nam, - (struct ifnet *)control, p)); + return (in_control(so, (long)m, (void *)nam, + (struct ifnet *)control, l)); + + s = splsoftnet(); if (req == PRU_PURGEIF) { in_pcbpurgeif0(&udbtable, (struct ifnet *)control); in_purgeif((struct ifnet *)control); in_pcbpurgeif(&udbtable, (struct ifnet *)control); + splx(s); return (0); } - s = splsoftnet(); inp = sotoinpcb(so); #ifdef DIAGNOSTIC if (req != PRU_SEND && req != PRU_SENDOOB && control) @@ -1241,7 +1228,7 @@ udp_usrreq(struct socket *so, int req, s break; case PRU_BIND: - error = in_pcbbind(inp, nam, p); + error = in_pcbbind(inp, nam, l); break; case PRU_LISTEN: @@ -1249,7 +1236,7 @@ udp_usrreq(struct socket *so, int req, s break; case PRU_CONNECT: - error = in_pcbconnect(inp, nam, p); + error = in_pcbconnect(inp, nam, l); if (error) break; soisconnected(so); @@ -1291,7 +1278,7 @@ udp_usrreq(struct socket *so, int req, s error = EISCONN; goto die; } - error = in_pcbconnect(inp, nam, p); + error = in_pcbconnect(inp, nam, l); if (error) goto die; } else { @@ -1347,6 +1334,38 @@ release: return (error); } +static void +udpstat_convert_to_user_cb(void *v1, void *v2, struct cpu_info *ci) +{ + uint64_t *udpsc = v1; + uint64_t *udps = v2; + u_int i; + + for (i = 0; i < UDP_NSTATS; i++) + udps[i] += udpsc[i]; +} + +static void +udpstat_convert_to_user(uint64_t *udps) +{ + + memset(udps, 0, sizeof(uint64_t) * UDP_NSTATS); + percpu_foreach(udpstat_percpu, udpstat_convert_to_user_cb, udps); +} + +static int +sysctl_net_inet_udp_stats(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + uint64_t udps[UDP_NSTATS]; + + udpstat_convert_to_user(udps); + node = *rnode; + node.sysctl_data = udps; + node.sysctl_size = sizeof(udps); + return (sysctl_lookup(SYSCTLFN_CALL(&node))); +} + /* * Sysctl for udp variables. */ @@ -1409,12 +1428,20 @@ SYSCTL_SETUP(sysctl_net_inet_udp_setup, CTLFLAG_PERMANENT, CTLTYPE_STRUCT, "stats", SYSCTL_DESCR("UDP statistics"), - NULL, 0, &udpstat, sizeof(udpstat), + sysctl_net_inet_udp_stats, 0, NULL, 0, CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS, CTL_EOL); } #endif +void +udp_statinc(u_int stat) +{ + + KASSERT(stat < UDP_NSTATS); + UDP_STATINC(stat); +} + #if (defined INET && defined IPSEC_NAT_T) /* * Returns: @@ -1423,14 +1450,11 @@ SYSCTL_SETUP(sysctl_net_inet_udp_setup, * -1 if an error occurent and m was freed */ static int -udp4_espinudp(mp, off, src, so) - struct mbuf **mp; - int off; - struct sockaddr *src; - struct socket *so; +udp4_espinudp(struct mbuf **mp, int off, struct sockaddr *src, + struct socket *so) { size_t len; - caddr_t data; + void *data; struct inpcb *inp; size_t skip = 0; size_t minlen; @@ -1459,11 +1483,11 @@ udp4_espinudp(mp, off, src, so) } len = m->m_len - off; - data = mtod(m, caddr_t) + off; + data = mtod(m, char *) + off; inp = sotoinpcb(so); /* Ignore keepalive packets */ - if ((len == 1) && (data[0] == '\xff')) { + if ((len == 1) && (*(unsigned char *)data == 0xff)) { return 1; } @@ -1495,7 +1519,7 @@ udp4_espinudp(mp, off, src, so) * Get the UDP ports. They are handled in network * order everywhere in IPSEC_NAT_T code. */ - udphdr = (struct udphdr *)(data - skip); + udphdr = (struct udphdr *)((char *)data - skip); sport = udphdr->uh_sport; dport = udphdr->uh_dport; @@ -1515,7 +1539,7 @@ udp4_espinudp(mp, off, src, so) * <-skip-> */ iphdrlen = off - sizeof(struct udphdr); - memmove(mtod(m, caddr_t) + skip, mtod(m, caddr_t), iphdrlen); + memmove(mtod(m, char *) + skip, mtod(m, void *), iphdrlen); m_adj(m, skip); ip = mtod(m, struct ip *); @@ -1548,7 +1572,11 @@ udp4_espinudp(mp, off, src, so) ((u_int16_t *)(tag + 1))[1] = dport; m_tag_prepend(n, tag); +#ifdef FAST_IPSEC + ipsec4_common_input(n, iphdrlen, IPPROTO_ESP); +#else esp4_input(n, iphdrlen); +#endif /* We handled it, it shoudln't be handled by UDP */ return 1;