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 --- |