Deleted Added
sdiff udiff text old ( 71350 ) new ( 78064 )
full compact
1/* $FreeBSD: head/sys/netinet6/in6_pcb.c 71350 2001-01-21 22:23:11Z des $ */
2/* $KAME: in6_pcb.c,v 1.8 2000/06/09 00:37:02 itojun Exp $ */
3
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:

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

61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
67 */
68
69#include "opt_ipsec.h"
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/malloc.h>
74#include <sys/mbuf.h>
75#include <sys/domain.h>
76#include <sys/protosw.h>

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

94#include <netinet/ip6.h>
95#include <netinet/ip_var.h>
96#include <netinet6/ip6_var.h>
97#include <netinet6/nd6.h>
98#include <netinet/in_pcb.h>
99#include <netinet6/in6_pcb.h>
100
101#include "faith.h"
102
103#ifdef IPSEC
104#include <netinet6/ipsec.h>
105#include <netinet6/ah.h>
106#include <netinet6/ipsec6.h>
107#include <netinet6/ah6.h>
108#include <netkey/key.h>
109#endif /* IPSEC */
110
111struct in6_addr zeroin6_addr;
112
113int
114in6_pcbbind(inp, nam, p)
115 register struct inpcb *inp;

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

160
161 sin6->sin6_port = 0; /* yech... */
162 if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0)
163 return(EADDRNOTAVAIL);
164
165 /*
166 * XXX: bind to an anycast address might accidentally
167 * cause sending a packet with anycast source address.
168 */
169 if (ia &&
170 ((struct in6_ifaddr *)ia)->ia6_flags &
171 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
172 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
173 return(EADDRNOTAVAIL);
174 }
175 }
176 if (lport) {
177 struct inpcb *t;
178
179 /* GROSS */
180 if (ntohs(lport) < IPV6PORT_RESERVED && p &&

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

188 if (t &&
189 (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
190 !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
191 (t->inp_socket->so_options &
192 SO_REUSEPORT) == 0) &&
193 (so->so_cred->cr_uid !=
194 t->inp_socket->so_cred->cr_uid))
195 return (EADDRINUSE);
196 if (ip6_mapped_addr_on != 0 &&
197 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
198 struct sockaddr_in sin;
199
200 in6_sin6_2_sin(&sin, sin6);
201 t = in_pcblookup_local(pcbinfo,
202 sin.sin_addr, lport,
203 INPLOOKUP_WILDCARD);
204 if (t &&

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

210 INP_SOCKAF(t->inp_socket)))
211 return (EADDRINUSE);
212 }
213 }
214 t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
215 lport, wild);
216 if (t && (reuseport & t->inp_socket->so_options) == 0)
217 return(EADDRINUSE);
218 if (ip6_mapped_addr_on != 0 &&
219 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
220 struct sockaddr_in sin;
221
222 in6_sin6_2_sin(&sin, sin6);
223 t = in_pcblookup_local(pcbinfo, sin.sin_addr,
224 lport, wild);
225 if (t &&
226 (reuseport & t->inp_socket->so_options)

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

242 else {
243 inp->inp_lport = lport;
244 if (in_pcbinshash(inp) != 0) {
245 inp->in6p_laddr = in6addr_any;
246 inp->inp_lport = 0;
247 return (EAGAIN);
248 }
249 }
250 inp->in6p_flowinfo = sin6 ? sin6->sin6_flowinfo : 0; /*XXX*/
251 return(0);
252}
253
254/*
255 * Transform old in6_pcbconnect() into an inner subroutine for new
256 * in6_pcbconnect(): Do some validity-checking on the remote
257 * address (in mbuf 'nam') and then determine local host address
258 * (i.e., which interface) to use to access that remote host.

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

265
266int
267in6_pcbladdr(inp, nam, plocal_addr6)
268 register struct inpcb *inp;
269 struct sockaddr *nam;
270 struct in6_addr **plocal_addr6;
271{
272 register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
273 struct in6_pktinfo *pi;
274 struct ifnet *ifp = NULL;
275 int error = 0;
276
277 if (nam->sa_len != sizeof (*sin6))
278 return (EINVAL);
279 if (sin6->sin6_family != AF_INET6)
280 return (EAFNOSUPPORT);
281 if (sin6->sin6_port == 0)

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

356 error = in6_pcbbind(inp, (struct sockaddr *)0, p);
357 if (error)
358 return (error);
359 }
360 inp->in6p_laddr = *addr6;
361 }
362 inp->in6p_faddr = sin6->sin6_addr;
363 inp->inp_fport = sin6->sin6_port;
364 /*
365 * xxx kazu flowlabel is necessary for connect?
366 * but if this line is missing, the garbage value remains.
367 */
368 inp->in6p_flowinfo = sin6->sin6_flowinfo;
369 if ((inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) == 0 &&
370 ip6_auto_flowlabel != 0)
371 inp->in6p_flowinfo |=
372 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
373
374 in_pcbrehash(inp);
375 return (0);
376}
377
378#if 0
379/*
380 * Return an IPv6 address, which is the most appropriate for given

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

516 if (ro) {
517 if (ro->ro_rt &&
518 !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
519 RTFREE(ro->ro_rt);
520 ro->ro_rt = (struct rtentry *)0;
521 }
522 if (ro->ro_rt == (struct rtentry *)0 ||
523 ro->ro_rt->rt_ifp == (struct ifnet *)0) {
524 /* No route yet, so try to acquire one */
525 bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
526 ro->ro_dst.sin6_family = AF_INET6;
527 ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
528 ro->ro_dst.sin6_addr = *dst;
529 if (IN6_IS_ADDR_MULTICAST(dst)) {
530 ro->ro_rt = rtalloc1(&((struct route *)ro)
531 ->ro_dst, 0, 0UL);
532 } else {
533 rtalloc((struct route *)ro);
534 }
535 }
536

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

579#endif
580
581void
582in6_pcbdisconnect(inp)
583 struct inpcb *inp;
584{
585 bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
586 inp->inp_fport = 0;
587 in_pcbrehash(inp);
588 if (inp->inp_socket->so_state & SS_NOFDREF)
589 in6_pcbdetach(inp);
590}
591
592void
593in6_pcbdetach(inp)
594 struct inpcb *inp;

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

599#ifdef IPSEC
600 if (inp->in6p_sp != NULL)
601 ipsec6_delete_pcbpolicy(inp);
602#endif /* IPSEC */
603 inp->inp_gencnt = ++ipi->ipi_gencnt;
604 in_pcbremlists(inp);
605 sotoinpcb(so) = 0;
606 sofree(so);
607 if (inp->in6p_options)
608 m_freem(inp->in6p_options);
609 if (inp->in6p_outputopts) {
610 if (inp->in6p_outputopts->ip6po_rthdr &&
611 inp->in6p_outputopts->ip6po_route.ro_rt)
612 RTFREE(inp->in6p_outputopts->ip6po_route.ro_rt);
613 if (inp->in6p_outputopts->ip6po_m)
614 (void)m_free(inp->in6p_outputopts->ip6po_m);
615 free(inp->in6p_outputopts, M_IP6OPT);
616 }
617 if (inp->in6p_route.ro_rt)
618 rtfree(inp->in6p_route.ro_rt);
619 ip6_freemoptions(inp->in6p_moptions);
620
621 /* Check and free IPv4 related resources in case of mapped addr */
622 if (inp->inp_options)
623 (void)m_free(inp->inp_options);
624 ip_freemoptions(inp->inp_moptions);
625
626 inp->inp_vflag = 0;
627 zfree(ipi->ipi_zone, inp);
628}

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

756 * taken, depending on the ctlinput cmd. The caller must filter any
757 * cmds that are uninteresting (e.g., no error in the map).
758 * Call the protocol specific routine (if any) to report
759 * any errors for each matching socket.
760 *
761 * Must be called at splnet.
762 */
763void
764in6_pcbnotify(head, dst, fport_arg, laddr6, lport_arg, cmd, notify)
765 struct inpcbhead *head;
766 struct sockaddr *dst;
767 u_int fport_arg, lport_arg;
768 struct in6_addr *laddr6;
769 int cmd;
770 void (*notify) __P((struct inpcb *, int));
771{
772 struct inpcb *inp, *ninp;
773 struct in6_addr faddr6;
774 u_short fport = fport_arg, lport = lport_arg;
775 int errno, s;
776 int do_rtchange = (notify == in6_rtchange);
777
778 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
779 return;
780 faddr6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
781 if (IN6_IS_ADDR_UNSPECIFIED(&faddr6))
782 return;
783
784 /*
785 * Redirects go to all references to the destination,
786 * and use in6_rtchange to invalidate the route cache.
787 * Dead host indications: also use in6_rtchange to invalidate
788 * the cache, and deliver the error to all the sockets.
789 * Otherwise, if we have knowledge of the local port and address,
790 * deliver only to that socket.
791 */
792 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
793 fport = 0;
794 lport = 0;
795 bzero((caddr_t)laddr6, sizeof(*laddr6));
796
797 do_rtchange = 1;
798 }
799 errno = inet6ctlerrmap[cmd];
800 s = splnet();
801 for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
802 ninp = LIST_NEXT(inp, inp_list);
803
804 if ((inp->inp_vflag & INP_IPV6) == NULL)
805 continue;
806
807 if (do_rtchange) {
808 /*
809 * Since a non-connected PCB might have a cached route,
810 * we always call in6_rtchange without matching
811 * the PCB to the src/dst pair.
812 *
813 * XXX: we assume in6_rtchange does not free the PCB.
814 */
815 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_route.ro_dst.sin6_addr,
816 &faddr6))
817 in6_rtchange(inp, errno);
818
819 if (notify == in6_rtchange)
820 continue; /* there's nothing to do any more */
821 }
822
823 if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &faddr6) ||
824 inp->inp_socket == 0 ||
825 (lport && inp->inp_lport != lport) ||
826 (!IN6_IS_ADDR_UNSPECIFIED(laddr6) &&
827 !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr6)) ||
828 (fport && inp->inp_fport != fport))
829 continue;
830
831 if (notify)
832 (*notify)(inp, errno);
833 }
834 splx(s);
835}
836
837/*
838 * Lookup a PCB based on the local address and port.
839 */
840struct inpcb *

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

985 struct in6_addr *faddr, *laddr;
986 u_int fport_arg, lport_arg;
987 int wildcard;
988 struct ifnet *ifp;
989{
990 struct inpcbhead *head;
991 register struct inpcb *inp;
992 u_short fport = fport_arg, lport = lport_arg;
993
994 /*
995 * First look for an exact match.
996 */
997 head = &pcbinfo->hashbase[INP_PCBHASH(faddr->s6_addr32[3] /* XXX */,
998 lport, fport,
999 pcbinfo->hashmask)];
1000 LIST_FOREACH(inp, head, inp_hash) {
1001 if ((inp->inp_vflag & INP_IPV6) == 0)

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

1015
1016 head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0,
1017 pcbinfo->hashmask)];
1018 LIST_FOREACH(inp, head, inp_hash) {
1019 if ((inp->inp_vflag & INP_IPV6) == 0)
1020 continue;
1021 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1022 inp->inp_lport == lport) {
1023#if defined(NFAITH) && NFAITH > 0
1024 if (ifp && ifp->if_type == IFT_FAITH &&
1025 (inp->inp_flags & INP_FAITH) == 0)
1026 continue;
1027#endif
1028 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
1029 laddr))
1030 return (inp);
1031 else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
1032 local_wild = inp;
1033 }
1034 }
1035 return (local_wild);

--- 26 unchanged lines hidden ---