Deleted Added
full compact
udp6_usrreq.c (62573) udp6_usrreq.c (62587)
1/* $FreeBSD: head/sys/netinet6/udp6_usrreq.c 62587 2000-07-04 16:35:15Z itojun $ */
2/* $KAME: udp6_usrreq.c,v 1.11 2000/06/18 06:23:06 jinmei Exp $ */
3
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 *
62 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright

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

58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
63 * $FreeBSD: head/sys/netinet6/udp6_usrreq.c 62573 2000-07-04 11:25:35Z phk $
64 */
65
66 */
67
68#include "opt_inet.h"
69#include "opt_inet6.h"
66#include "opt_ipsec.h"
67
68#include <sys/param.h>
69#include <sys/kernel.h>
70#include <sys/mbuf.h>
71#include <sys/protosw.h>
72#include <sys/socket.h>
73#include <sys/socketvar.h>

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

85#include <netinet/in.h>
86#include <netinet/in_systm.h>
87#include <netinet/ip.h>
88#include <netinet/in_pcb.h>
89#include <netinet/in_var.h>
90#include <netinet/ip_var.h>
91#include <netinet/udp.h>
92#include <netinet/udp_var.h>
70#include "opt_ipsec.h"
71
72#include <sys/param.h>
73#include <sys/kernel.h>
74#include <sys/mbuf.h>
75#include <sys/protosw.h>
76#include <sys/socket.h>
77#include <sys/socketvar.h>

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

89#include <netinet/in.h>
90#include <netinet/in_systm.h>
91#include <netinet/ip.h>
92#include <netinet/in_pcb.h>
93#include <netinet/in_var.h>
94#include <netinet/ip_var.h>
95#include <netinet/udp.h>
96#include <netinet/udp_var.h>
93#include <netinet6/ip6.h>
97#include
94#include <netinet6/ip6_var.h>
95#include <netinet6/in6_pcb.h>
98#include <netinet6/ip6_var.h>
99#include <netinet6/in6_pcb.h>
96#include <netinet6/icmp6.h>
100#include
97#include <netinet6/udp6_var.h>
98#include <netinet6/ip6protosw.h>
99
100#ifdef IPSEC
101#include <netinet6/ipsec.h>
102#include <netinet6/ipsec6.h>
103#endif /*IPSEC*/
104

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

397 struct sockaddr *sa;
398 void *d;
399{
400 register struct udphdr *uhp;
401 struct udphdr uh;
402 struct sockaddr_in6 sa6;
403 struct ip6_hdr *ip6;
404 struct mbuf *m;
101#include <netinet6/udp6_var.h>
102#include <netinet6/ip6protosw.h>
103
104#ifdef IPSEC
105#include <netinet6/ipsec.h>
106#include <netinet6/ipsec6.h>
107#endif /*IPSEC*/
108

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

401 struct sockaddr *sa;
402 void *d;
403{
404 register struct udphdr *uhp;
405 struct udphdr uh;
406 struct sockaddr_in6 sa6;
407 struct ip6_hdr *ip6;
408 struct mbuf *m;
405 int off;
409 int off = 0;
410 void (*notify) __P((struct inpcb *, int)) = udp_notify;
406
407 if (sa->sa_family != AF_INET6 ||
408 sa->sa_len != sizeof(struct sockaddr_in6))
409 return;
410
411
412 if (sa->sa_family != AF_INET6 ||
413 sa->sa_len != sizeof(struct sockaddr_in6))
414 return;
415
411 off = 0;
412 if (!PRC_IS_REDIRECT(cmd) &&
413 ((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
416 if ((unsigned)cmd >= PRC_NCMDS)
414 return;
417 return;
418 if (PRC_IS_REDIRECT(cmd))
419 notify = in6_rtchange, d = NULL;
420 else if (cmd == PRC_HOSTDEAD)
421 d = NULL;
422 else if (inet6ctlerrmap[cmd] == 0)
423 return;
415
416 /* if the parameter is from icmp6, decode it. */
417 if (d != NULL) {
418 struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
419 m = ip6cp->ip6c_m;
420 ip6 = ip6cp->ip6c_ip6;
421 off = ip6cp->ip6c_off;
422 } else {
423 m = NULL;
424 ip6 = NULL;
425 }
426
427 /* translate addresses into internal form */
428 sa6 = *(struct sockaddr_in6 *)sa;
424
425 /* if the parameter is from icmp6, decode it. */
426 if (d != NULL) {
427 struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
428 m = ip6cp->ip6c_m;
429 ip6 = ip6cp->ip6c_ip6;
430 off = ip6cp->ip6c_off;
431 } else {
432 m = NULL;
433 ip6 = NULL;
434 }
435
436 /* translate addresses into internal form */
437 sa6 = *(struct sockaddr_in6 *)sa;
429 if (m != NULL && IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr))
438 if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) && m && m->m_pkthdr.rcvif)
430 sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
431
432 if (ip6) {
433 /*
434 * XXX: We assume that when IPV6 is non NULL,
435 * M and OFF are valid.
436 */
437 struct in6_addr s;

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

447 * so we compromise on this copy...
448 */
449 m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
450 uhp = &uh;
451 } else
452 uhp = (struct udphdr *)(mtod(m, caddr_t) + off);
453 (void) in6_pcbnotify(&udb, (struct sockaddr *)&sa6,
454 uhp->uh_dport, &s,
439 sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
440
441 if (ip6) {
442 /*
443 * XXX: We assume that when IPV6 is non NULL,
444 * M and OFF are valid.
445 */
446 struct in6_addr s;

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

456 * so we compromise on this copy...
457 */
458 m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
459 uhp = &uh;
460 } else
461 uhp = (struct udphdr *)(mtod(m, caddr_t) + off);
462 (void) in6_pcbnotify(&udb, (struct sockaddr *)&sa6,
463 uhp->uh_dport, &s,
455 uhp->uh_sport, cmd, udp_notify);
464 uhp->uh_sport, cmd, notify);
456 } else
457 (void) in6_pcbnotify(&udb, (struct sockaddr *)&sa6, 0,
465 } else
466 (void) in6_pcbnotify(&udb, (struct sockaddr *)&sa6, 0,
458 &zeroin6_addr, 0, cmd, udp_notify);
467 &zeroin6_addr, 0, cmd, notify);
459}
460
461static int
462udp6_getcred(SYSCTL_HANDLER_ARGS)
463{
464 struct sockaddr_in6 addrs[2];
465 struct inpcb *inp;
466 int error, s;
467
468 error = suser(req->p);
469 if (error)
470 return (error);
468}
469
470static int
471udp6_getcred(SYSCTL_HANDLER_ARGS)
472{
473 struct sockaddr_in6 addrs[2];
474 struct inpcb *inp;
475 int error, s;
476
477 error = suser(req->p);
478 if (error)
479 return (error);
480
481 if (req->newlen != sizeof(addrs))
482 return (EINVAL);
483 if (req->oldlen != sizeof(struct ucred))
484 return (EINVAL);
471 error = SYSCTL_IN(req, addrs, sizeof(addrs));
472 if (error)
473 return (error);
474 s = splnet();
475 inp = in6_pcblookup_hash(&udbinfo, &addrs[1].sin6_addr,
476 addrs[1].sin6_port,
477 &addrs[0].sin6_addr, addrs[0].sin6_port,
478 1, NULL);

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

487 splx(s);
488 return (error);
489}
490
491SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
492 0, 0,
493 udp6_getcred, "S,ucred", "Get the ucred of a UDP6 connection");
494
485 error = SYSCTL_IN(req, addrs, sizeof(addrs));
486 if (error)
487 return (error);
488 s = splnet();
489 inp = in6_pcblookup_hash(&udbinfo, &addrs[1].sin6_addr,
490 addrs[1].sin6_port,
491 &addrs[0].sin6_addr, addrs[0].sin6_port,
492 1, NULL);

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

501 splx(s);
502 return (error);
503}
504
505SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
506 0, 0,
507 udp6_getcred, "S,ucred", "Get the ucred of a UDP6 connection");
508
495int
496udp6_output(in6p, m, addr6, control, p)
497 register struct inpcb *in6p;
498 struct mbuf *m;
499 struct sockaddr *addr6;
500 struct mbuf *control;
501 struct proc *p;
502{
503 register int ulen = m->m_pkthdr.len;
504 int plen = sizeof(struct udphdr) + ulen;
505 struct ip6_hdr *ip6;
506 struct udphdr *udp6;
507 struct in6_addr laddr6;
508 int s = 0, error = 0;
509 struct ip6_pktopts opt, *stickyopt = in6p->in6p_outputopts;
510
511 if (control) {
512 if ((error = ip6_setpktoptions(control, &opt, suser(p))) != 0)
513 goto release;
514 in6p->in6p_outputopts = &opt;
515 }
516
517 if (addr6) {
518 laddr6 = in6p->in6p_laddr;
519 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
520 error = EISCONN;
521 goto release;
522 }
523 /*
524 * Must block input while temporarily connected.
525 */
526 s = splnet();
527 /*
528 * XXX: the user might want to overwrite the local address
529 * via an ancillary data.
530 */
531 bzero(&in6p->in6p_laddr, sizeof(struct in6_addr));
532 error = in6_pcbconnect(in6p, addr6, p);
533 if (error) {
534 splx(s);
535 goto release;
536 }
537 } else {
538 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
539 error = ENOTCONN;
540 goto release;
541 }
542 }
543 /*
544 * Calculate data length and get a mbuf
545 * for UDP and IP6 headers.
546 */
547 M_PREPEND(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr),
548 M_DONTWAIT);
549 if (m == 0) {
550 error = ENOBUFS;
551 if (addr6)
552 splx(s);
553 goto release;
554 }
555
556 /*
557 * Stuff checksum and output datagram.
558 */
559 ip6 = mtod(m, struct ip6_hdr *);
560 ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
561 (in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK);
562 ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
563 (IPV6_VERSION & IPV6_VERSION_MASK);
564 /* ip6_plen will be filled in ip6_output. */
565 ip6->ip6_nxt = IPPROTO_UDP;
566 ip6->ip6_hlim = in6_selecthlim(in6p,
567 in6p->in6p_route.ro_rt ?
568 in6p->in6p_route.ro_rt->rt_ifp :
569 NULL);
570 ip6->ip6_src = in6p->in6p_laddr;
571 ip6->ip6_dst = in6p->in6p_faddr;
572
573 udp6 = (struct udphdr *)(ip6 + 1);
574 udp6->uh_sport = in6p->in6p_lport;
575 udp6->uh_dport = in6p->in6p_fport;
576 udp6->uh_ulen = htons((u_short)plen);
577 udp6->uh_sum = 0;
578
579 if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
580 sizeof(struct ip6_hdr), plen)) == 0) {
581 udp6->uh_sum = 0xffff;
582 }
583
584 udpstat.udps_opackets++;
585
586#ifdef IPSEC
587 m->m_pkthdr.rcvif = (struct ifnet *)in6p->in6p_socket;
588#endif /*IPSEC*/
589 error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route,
590 IPV6_SOCKINMRCVIF, in6p->in6p_moptions, NULL);
591
592 if (addr6) {
593 in6_pcbdisconnect(in6p);
594 in6p->in6p_laddr = laddr6;
595 splx(s);
596 }
597 goto releaseopt;
598
599release:
600 m_freem(m);
601
602releaseopt:
603 if (control) {
604 in6p->in6p_outputopts = stickyopt;
605 m_freem(control);
606 }
607 return(error);
608}
609
610static int
611udp6_abort(struct socket *so)
612{
613 struct inpcb *inp;
614 int s;
615
616 inp = sotoinpcb(so);
617 if (inp == 0)

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

727 if (error == 0) {
728 inp->inp_vflag |= INP_IPV4;
729 inp->inp_vflag &= ~INP_IPV6;
730 soisconnected(so);
731 }
732 return error;
733 }
734 }
509static int
510udp6_abort(struct socket *so)
511{
512 struct inpcb *inp;
513 int s;
514
515 inp = sotoinpcb(so);
516 if (inp == 0)

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

626 if (error == 0) {
627 inp->inp_vflag |= INP_IPV4;
628 inp->inp_vflag &= ~INP_IPV6;
629 soisconnected(so);
630 }
631 return error;
632 }
633 }
634
735 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
736 return EISCONN;
737 s = splnet();
738 error = in6_pcbconnect(inp, nam, p);
635 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
636 return EISCONN;
637 s = splnet();
638 error = in6_pcbconnect(inp, nam, p);
639 if (ip6_auto_flowlabel) {
640 inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
641 inp->in6p_flowinfo |=
642 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
643 }
739 splx(s);
740 if (error == 0) {
741 inp->inp_vflag &= ~INP_IPV4;
742 inp->inp_vflag |= INP_IPV6;
743 soisconnected(so);
744 }
745 return error;
746}

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

788 return 0;
789}
790
791static int
792udp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
793 struct mbuf *control, struct proc *p)
794{
795 struct inpcb *inp;
644 splx(s);
645 if (error == 0) {
646 inp->inp_vflag &= ~INP_IPV4;
647 inp->inp_vflag |= INP_IPV6;
648 soisconnected(so);
649 }
650 return error;
651}

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

693 return 0;
694}
695
696static int
697udp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
698 struct mbuf *control, struct proc *p)
699{
700 struct inpcb *inp;
701 int error = 0;
796
797 inp = sotoinpcb(so);
798 if (inp == 0) {
702
703 inp = sotoinpcb(so);
704 if (inp == 0) {
799 m_freem(m);
800 return EINVAL;
705 error = EINVAL;
706 goto bad;
801 }
802
707 }
708
803 if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0) {
709 if (addr) {
710 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
711 error = EINVAL;
712 goto bad;
713 }
714 if (addr->sa_family != AF_INET6) {
715 error = EAFNOSUPPORT;
716 goto bad;
717 }
718 }
719
720 if (ip6_mapped_addr_on) {
804 int hasv4addr;
805 struct sockaddr_in6 *sin6 = 0;
806
807 if (addr == 0)
808 hasv4addr = (inp->inp_vflag & INP_IPV4);
809 else {
810 sin6 = (struct sockaddr_in6 *)addr;
811 hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)
812 ? 1 : 0;
813 }
814 if (hasv4addr) {
815 struct pr_usrreqs *pru;
721 int hasv4addr;
722 struct sockaddr_in6 *sin6 = 0;
723
724 if (addr == 0)
725 hasv4addr = (inp->inp_vflag & INP_IPV4);
726 else {
727 sin6 = (struct sockaddr_in6 *)addr;
728 hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)
729 ? 1 : 0;
730 }
731 if (hasv4addr) {
732 struct pr_usrreqs *pru;
816 int error;
817
818 if (sin6)
819 in6_sin6_2_sin_in_sock(addr);
820 pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
821 error = ((*pru->pru_send)(so, flags, m, addr, control,
822 p));
823 /* addr will just be freed in sendit(). */
824 return error;
825 }
826 }
827
828 return udp6_output(inp, m, addr, control, p);
733
734 if (sin6)
735 in6_sin6_2_sin_in_sock(addr);
736 pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
737 error = ((*pru->pru_send)(so, flags, m, addr, control,
738 p));
739 /* addr will just be freed in sendit(). */
740 return error;
741 }
742 }
743
744 return udp6_output(inp, m, addr, control, p);
745
746 bad:
747 m_freem(m);
748 return(error);
829}
830
831struct pr_usrreqs udp6_usrreqs = {
832 udp6_abort, pru_accept_notsupp, udp6_attach, udp6_bind, udp6_connect,
833 pru_connect2_notsupp, in6_control, udp6_detach, udp6_disconnect,
834 pru_listen_notsupp, in6_mapped_peeraddr, pru_rcvd_notsupp,
835 pru_rcvoob_notsupp, udp6_send, pru_sense_null, udp_shutdown,
836 in6_mapped_sockaddr, sosend, soreceive, sopoll
837};
749}
750
751struct pr_usrreqs udp6_usrreqs = {
752 udp6_abort, pru_accept_notsupp, udp6_attach, udp6_bind, udp6_connect,
753 pru_connect2_notsupp, in6_control, udp6_detach, udp6_disconnect,
754 pru_listen_notsupp, in6_mapped_peeraddr, pru_rcvd_notsupp,
755 pru_rcvoob_notsupp, udp6_send, pru_sense_null, udp_shutdown,
756 in6_mapped_sockaddr, sosend, soreceive, sopoll
757};