Deleted Added
full compact
udp_usrreq.c (265909) udp_usrreq.c (269699)
1/*-
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3 * The Regents of the University of California.
4 * Copyright (c) 2008 Robert N. M. Watson
5 * Copyright (c) 2010-2011 Juniper Networks, Inc.
6 * Copyright (c) 2014 Kevin Lo
7 * All rights reserved.
8 *

--- 23 unchanged lines hidden (view full) ---

32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
37 */
38
39#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3 * The Regents of the University of California.
4 * Copyright (c) 2008 Robert N. M. Watson
5 * Copyright (c) 2010-2011 Juniper Networks, Inc.
6 * Copyright (c) 2014 Kevin Lo
7 * All rights reserved.
8 *

--- 23 unchanged lines hidden (view full) ---

32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: head/sys/netinet/udp_usrreq.c 265909 2014-05-12 09:46:48Z tuexen $");
40__FBSDID("$FreeBSD: head/sys/netinet/udp_usrreq.c 269699 2014-08-08 01:57:15Z kevlo $");
41
42#include "opt_ipfw.h"
43#include "opt_inet.h"
44#include "opt_inet6.h"
45#include "opt_ipsec.h"
46
47#include <sys/param.h>
48#include <sys/domain.h>

--- 314 unchanged lines hidden (view full) ---

363 m_freem(n);
364 if (opts)
365 m_freem(opts);
366 UDPSTAT_INC(udps_fullsock);
367 } else
368 sorwakeup_locked(so);
369}
370
41
42#include "opt_ipfw.h"
43#include "opt_inet.h"
44#include "opt_inet6.h"
45#include "opt_ipsec.h"
46
47#include <sys/param.h>
48#include <sys/domain.h>

--- 314 unchanged lines hidden (view full) ---

363 m_freem(n);
364 if (opts)
365 m_freem(opts);
366 UDPSTAT_INC(udps_fullsock);
367 } else
368 sorwakeup_locked(so);
369}
370
371void
372udp_input(struct mbuf *m, int off)
371int
372udp_input(struct mbuf **mp, int *offp, int proto)
373{
373{
374 int iphlen = off;
375 struct ip *ip;
376 struct udphdr *uh;
377 struct ifnet *ifp;
378 struct inpcb *inp;
379 uint16_t len, ip_len;
380 struct inpcbinfo *pcbinfo;
381 struct ip save_ip;
382 struct sockaddr_in udp_in;
374 struct ip *ip;
375 struct udphdr *uh;
376 struct ifnet *ifp;
377 struct inpcb *inp;
378 uint16_t len, ip_len;
379 struct inpcbinfo *pcbinfo;
380 struct ip save_ip;
381 struct sockaddr_in udp_in;
382 struct mbuf *m;
383 struct m_tag *fwd_tag;
383 struct m_tag *fwd_tag;
384 int cscov_partial;
385 uint8_t pr;
384 int cscov_partial, iphlen;
386
385
386 m = *mp;
387 iphlen = *offp;
387 ifp = m->m_pkthdr.rcvif;
388 ifp = m->m_pkthdr.rcvif;
389 *mp = NULL;
388 UDPSTAT_INC(udps_ipackets);
389
390 /*
391 * Strip IP options, if any; should skip this, make available to
392 * user, and use on returned packets, but we don't yet have a way to
393 * check the checksum with options still present.
394 */
395 if (iphlen > sizeof (struct ip)) {
396 ip_stripoptions(m);
397 iphlen = sizeof(struct ip);
398 }
399
400 /*
401 * Get IP and UDP header together in first mbuf.
402 */
403 ip = mtod(m, struct ip *);
404 if (m->m_len < iphlen + sizeof(struct udphdr)) {
405 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == NULL) {
406 UDPSTAT_INC(udps_hdrops);
390 UDPSTAT_INC(udps_ipackets);
391
392 /*
393 * Strip IP options, if any; should skip this, make available to
394 * user, and use on returned packets, but we don't yet have a way to
395 * check the checksum with options still present.
396 */
397 if (iphlen > sizeof (struct ip)) {
398 ip_stripoptions(m);
399 iphlen = sizeof(struct ip);
400 }
401
402 /*
403 * Get IP and UDP header together in first mbuf.
404 */
405 ip = mtod(m, struct ip *);
406 if (m->m_len < iphlen + sizeof(struct udphdr)) {
407 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == NULL) {
408 UDPSTAT_INC(udps_hdrops);
407 return;
409 return (IPPROTO_DONE);
408 }
409 ip = mtod(m, struct ip *);
410 }
411 uh = (struct udphdr *)((caddr_t)ip + iphlen);
410 }
411 ip = mtod(m, struct ip *);
412 }
413 uh = (struct udphdr *)((caddr_t)ip + iphlen);
412 pr = ip->ip_p;
413 cscov_partial = (pr == IPPROTO_UDPLITE) ? 1 : 0;
414 cscov_partial = (proto == IPPROTO_UDPLITE) ? 1 : 0;
414
415 /*
416 * Destination port of 0 is illegal, based on RFC768.
417 */
418 if (uh->uh_dport == 0)
419 goto badunlocked;
420
421 /*

--- 7 unchanged lines hidden (view full) ---

429 udp_in.sin_addr = ip->ip_src;
430
431 /*
432 * Make mbuf data length reflect UDP length. If not enough data to
433 * reflect UDP length, drop.
434 */
435 len = ntohs((u_short)uh->uh_ulen);
436 ip_len = ntohs(ip->ip_len) - iphlen;
415
416 /*
417 * Destination port of 0 is illegal, based on RFC768.
418 */
419 if (uh->uh_dport == 0)
420 goto badunlocked;
421
422 /*

--- 7 unchanged lines hidden (view full) ---

430 udp_in.sin_addr = ip->ip_src;
431
432 /*
433 * Make mbuf data length reflect UDP length. If not enough data to
434 * reflect UDP length, drop.
435 */
436 len = ntohs((u_short)uh->uh_ulen);
437 ip_len = ntohs(ip->ip_len) - iphlen;
437 if (pr == IPPROTO_UDPLITE && len == 0) {
438 if (proto == IPPROTO_UDPLITE && len == 0) {
438 /* Zero means checksum over the complete packet. */
439 len = ip_len;
440 cscov_partial = 0;
441 }
442 if (ip_len != len) {
443 if (len > ip_len || len < sizeof(struct udphdr)) {
444 UDPSTAT_INC(udps_badlen);
445 goto badunlocked;
446 }
439 /* Zero means checksum over the complete packet. */
440 len = ip_len;
441 cscov_partial = 0;
442 }
443 if (ip_len != len) {
444 if (len > ip_len || len < sizeof(struct udphdr)) {
445 UDPSTAT_INC(udps_badlen);
446 goto badunlocked;
447 }
447 if (pr == IPPROTO_UDP)
448 if (proto == IPPROTO_UDP)
448 m_adj(m, len - ip_len);
449 }
450
451 /*
452 * Save a copy of the IP header in case we want restore it for
453 * sending an ICMP error message in response.
454 */
455 if (!V_udp_blackhole)

--- 9 unchanged lines hidden (view full) ---

465
466 if ((m->m_pkthdr.csum_flags & CSUM_DATA_VALID) &&
467 !cscov_partial) {
468 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
469 uh_sum = m->m_pkthdr.csum_data;
470 else
471 uh_sum = in_pseudo(ip->ip_src.s_addr,
472 ip->ip_dst.s_addr, htonl((u_short)len +
449 m_adj(m, len - ip_len);
450 }
451
452 /*
453 * Save a copy of the IP header in case we want restore it for
454 * sending an ICMP error message in response.
455 */
456 if (!V_udp_blackhole)

--- 9 unchanged lines hidden (view full) ---

466
467 if ((m->m_pkthdr.csum_flags & CSUM_DATA_VALID) &&
468 !cscov_partial) {
469 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
470 uh_sum = m->m_pkthdr.csum_data;
471 else
472 uh_sum = in_pseudo(ip->ip_src.s_addr,
473 ip->ip_dst.s_addr, htonl((u_short)len +
473 m->m_pkthdr.csum_data + pr));
474 m->m_pkthdr.csum_data + proto));
474 uh_sum ^= 0xffff;
475 } else {
476 char b[9];
477
478 bcopy(((struct ipovly *)ip)->ih_x1, b, 9);
479 bzero(((struct ipovly *)ip)->ih_x1, 9);
475 uh_sum ^= 0xffff;
476 } else {
477 char b[9];
478
479 bcopy(((struct ipovly *)ip)->ih_x1, b, 9);
480 bzero(((struct ipovly *)ip)->ih_x1, 9);
480 ((struct ipovly *)ip)->ih_len = (pr == IPPROTO_UDP) ?
481 ((struct ipovly *)ip)->ih_len = (proto == IPPROTO_UDP) ?
481 uh->uh_ulen : htons(ip_len);
482 uh_sum = in_cksum(m, len + sizeof (struct ip));
483 bcopy(b, ((struct ipovly *)ip)->ih_x1, 9);
484 }
485 if (uh_sum) {
486 UDPSTAT_INC(udps_badsum);
487 m_freem(m);
482 uh->uh_ulen : htons(ip_len);
483 uh_sum = in_cksum(m, len + sizeof (struct ip));
484 bcopy(b, ((struct ipovly *)ip)->ih_x1, 9);
485 }
486 if (uh_sum) {
487 UDPSTAT_INC(udps_badsum);
488 m_freem(m);
488 return;
489 return (IPPROTO_DONE);
489 }
490 } else
491 UDPSTAT_INC(udps_nosum);
492
490 }
491 } else
492 UDPSTAT_INC(udps_nosum);
493
493 pcbinfo = get_inpcbinfo(pr);
494 pcbinfo = get_inpcbinfo(proto);
494 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
495 in_broadcast(ip->ip_dst, ifp)) {
496 struct inpcb *last;
497 struct inpcbhead *pcblist;
498 struct ip_moptions *imo;
499
500 INP_INFO_RLOCK(pcbinfo);
495 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
496 in_broadcast(ip->ip_dst, ifp)) {
497 struct inpcb *last;
498 struct inpcbhead *pcblist;
499 struct ip_moptions *imo;
500
501 INP_INFO_RLOCK(pcbinfo);
501 pcblist = get_pcblist(pr);
502 pcblist = get_pcblist(proto);
502 last = NULL;
503 LIST_FOREACH(inp, pcblist, inp_list) {
504 if (inp->inp_lport != uh->uh_dport)
505 continue;
506#ifdef INET6
507 if ((inp->inp_vflag & INP_IPV4) == 0)
508 continue;
509#endif

--- 77 unchanged lines hidden (view full) ---

587 if (inp)
588 INP_RUNLOCK(inp);
589 INP_INFO_RUNLOCK(pcbinfo);
590 goto badunlocked;
591 }
592 udp_append(last, ip, m, iphlen, &udp_in);
593 INP_RUNLOCK(last);
594 INP_INFO_RUNLOCK(pcbinfo);
503 last = NULL;
504 LIST_FOREACH(inp, pcblist, inp_list) {
505 if (inp->inp_lport != uh->uh_dport)
506 continue;
507#ifdef INET6
508 if ((inp->inp_vflag & INP_IPV4) == 0)
509 continue;
510#endif

--- 77 unchanged lines hidden (view full) ---

588 if (inp)
589 INP_RUNLOCK(inp);
590 INP_INFO_RUNLOCK(pcbinfo);
591 goto badunlocked;
592 }
593 udp_append(last, ip, m, iphlen, &udp_in);
594 INP_RUNLOCK(last);
595 INP_INFO_RUNLOCK(pcbinfo);
595 return;
596 return (IPPROTO_DONE);
596 }
597
598 /*
599 * Locate pcb for datagram.
600 */
601
602 /*
603 * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.

--- 45 unchanged lines hidden (view full) ---

649 goto badunlocked;
650 }
651 if (V_udp_blackhole)
652 goto badunlocked;
653 if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0)
654 goto badunlocked;
655 *ip = save_ip;
656 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
597 }
598
599 /*
600 * Locate pcb for datagram.
601 */
602
603 /*
604 * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.

--- 45 unchanged lines hidden (view full) ---

650 goto badunlocked;
651 }
652 if (V_udp_blackhole)
653 goto badunlocked;
654 if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0)
655 goto badunlocked;
656 *ip = save_ip;
657 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
657 return;
658 return (IPPROTO_DONE);
658 }
659
660 /*
661 * Check the minimum TTL for socket.
662 */
663 INP_RLOCK_ASSERT(inp);
664 if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) {
665 INP_RUNLOCK(inp);
666 m_freem(m);
659 }
660
661 /*
662 * Check the minimum TTL for socket.
663 */
664 INP_RLOCK_ASSERT(inp);
665 if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) {
666 INP_RUNLOCK(inp);
667 m_freem(m);
667 return;
668 return (IPPROTO_DONE);
668 }
669 if (cscov_partial) {
670 struct udpcb *up;
671
672 up = intoudpcb(inp);
673 if (up->u_rxcslen > len) {
674 INP_RUNLOCK(inp);
675 m_freem(m);
669 }
670 if (cscov_partial) {
671 struct udpcb *up;
672
673 up = intoudpcb(inp);
674 if (up->u_rxcslen > len) {
675 INP_RUNLOCK(inp);
676 m_freem(m);
676 return;
677 return (IPPROTO_DONE);
677 }
678 }
679
680 UDP_PROBE(receive, NULL, inp, ip, inp, uh);
681 udp_append(inp, ip, m, iphlen, &udp_in);
682 INP_RUNLOCK(inp);
678 }
679 }
680
681 UDP_PROBE(receive, NULL, inp, ip, inp, uh);
682 udp_append(inp, ip, m, iphlen, &udp_in);
683 INP_RUNLOCK(inp);
683 return;
684 return (IPPROTO_DONE);
684
685badunlocked:
686 m_freem(m);
685
686badunlocked:
687 m_freem(m);
688 return (IPPROTO_DONE);
687}
688#endif /* INET */
689
690/*
691 * Notify a udp user of an asynchronous error; just wake up so that they can
692 * collect error status.
693 */
694struct inpcb *

--- 1103 unchanged lines hidden ---
689}
690#endif /* INET */
691
692/*
693 * Notify a udp user of an asynchronous error; just wake up so that they can
694 * collect error status.
695 */
696struct inpcb *

--- 1103 unchanged lines hidden ---