diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 1999-12-12 10:59:42 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 1999-12-12 10:59:42 +0000 |
commit | 376df55ebd35df17e1d5ca52378e19ed8f9d8463 (patch) | |
tree | a1ba1eecf470bdf510bf3c6866120dd6f397e73e | |
parent | 04ace694ea3f86e1156ff296634aeb041d31f803 (diff) |
fix IPv6 advanced API (RFC2292) for udp socket.
TODO: ditto for raw and tcp socket
-rw-r--r-- | sys/netinet/udp_usrreq.c | 134 |
1 files changed, 64 insertions, 70 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index ff65e76a6e2..a2d2d5a17bd 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.29 1999/12/08 06:50:20 itojun Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.30 1999/12/12 10:59:41 itojun Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -237,13 +237,10 @@ udp_input(m, va_alist) * (contd. from above...) Furthermore, we may want to strip options * for such things as ICMP errors, where options just get in the way. */ -#ifdef INET6 - if (ip) -#endif /* INET6 */ - if (iphlen > sizeof (struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); - } + if (ip && iphlen > sizeof (struct ip)) { + ip_stripoptions(m, (struct mbuf *)0); + iphlen = sizeof(struct ip); + } /* * Get IP and UDP header together in first mbuf. @@ -387,9 +384,7 @@ udp_input(m, va_alist) */ iphlen += sizeof(struct udphdr); - m->m_len -= iphlen; - m->m_pkthdr.len -= iphlen; - m->m_data += iphlen; + /* * Locate pcb(s) for datagram. * (Algorithm copied from raw_intr().) @@ -435,14 +430,12 @@ udp_input(m, va_alist) struct mbuf *n; if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + opts = NULL; #ifdef INET6 -#if 0 /*XXX*/ - if (ipv6) - opts = ipv6_headertocontrol(m, iphlen, ((struct inpcb *)last->so_pcb)->inp_flags); -#else - opts = NULL; -#endif + if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) + ip6_savecontrol(inp, &opts, ipv6, n); #endif /* INET6 */ + m_adj(n, iphlen); if (sbappendaddr(&last->so_rcv, #ifdef INET6 /* @@ -454,7 +447,7 @@ udp_input(m, va_alist) & INP_IPV6) && ip) ? (struct sockaddr *)&src_v4mapped : #endif /* INET6 */ - &srcsa.sa, n, (struct mbuf *)0) == 0) { + &srcsa.sa, n, opts) == 0) { m_freem(n); udpstat.udps_fullsock++; } else @@ -484,15 +477,12 @@ udp_input(m, va_alist) goto bad; } + opts = NULL; #ifdef INET6 -#if 0 /*XXX*/ - if (ipv6) - opts = ipv6_headertocontrol(m, iphlen, - ((struct inpcb *)last->so_pcb)->inp_flags); -#else - opts = NULL; -#endif + if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) + ip6_savecontrol(inp, &opts, ipv6, m); #endif /* INET6 */ + m_adj(m, iphlen); if (sbappendaddr(&last->so_rcv, #ifdef INET6 /* @@ -503,7 +493,7 @@ udp_input(m, va_alist) ((((struct inpcb *)last->so_pcb)->inp_flags & INP_IPV6) && ip) ? (struct sockaddr *)&src_v4mapped : #endif /* INET6 */ - &srcsa.sa, m, (struct mbuf *)0) == 0) { + &srcsa.sa, m, opts) == 0) { udpstat.udps_fullsock++; goto bad; } @@ -581,21 +571,14 @@ udp_input(m, va_alist) tdb_add_inp(tdb, inp); #endif /*IPSEC */ - if (inp->inp_flags & INP_CONTROLOPTS) { - struct mbuf **mp = &opts; - + opts = NULL; #ifdef INET6 - if (ipv6) { -#if 0 /*XXX*/ - if (inp->inp_flags & INP_IPV6) - opts = ipv6_headertocontrol(m, iphlen, - inp->inp_flags); -#else - opts = NULL; -#endif - } else - if (ip) + if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) + ip6_savecontrol(inp, &opts, ipv6, m); #endif /* INET6 */ + if (ip && (inp->inp_flags & INP_CONTROLOPTS)) { + struct mbuf **mp = &opts; + if (inp->inp_flags & INP_RECVDSTADDR) { *mp = udp_saveopt((caddr_t) &ip->ip_dst, sizeof(struct in_addr), IP_RECVDSTADDR); @@ -620,10 +603,7 @@ udp_input(m, va_alist) #endif } iphlen += sizeof(struct udphdr); - m->m_len -= iphlen; - m->m_pkthdr.len -= iphlen; - m->m_data += iphlen; - + m_adj(m, iphlen); if (sbappendaddr(&inp->inp_socket->so_rcv, #ifdef INET6 /* @@ -789,8 +769,8 @@ udp_output(m, va_alist) #ifdef INET6 register struct in6_addr laddr6; int v6packet = 0; - struct ifnet *forceif = NULL; struct sockaddr_in6 *sin6 = NULL; + struct ip6_pktopts opt, *stickyopt = NULL; #endif /* INET6 */ int pcbflags = 0; @@ -800,10 +780,21 @@ udp_output(m, va_alist) control = va_arg(ap, struct mbuf *); va_end(ap); -#ifndef INET6 - if (control) - m_freem(control); /* XXX */ -#endif /* INET6 */ +#ifdef INET6 + v6packet = ((inp->inp_flags & INP_IPV6) && + !(inp->inp_flags & INP_IPV6_MAPPED)); +#endif + +#ifdef INET6 + stickyopt = inp->inp_outputopts6; + if (control && v6packet) { + error = ip6_setpktoptions(control, &opt, + ((inp->inp_socket->so_state & SS_PRIV) != 0)); + if (error != 0) + goto release; + inp->inp_outputopts6 = &opt; + } +#endif if (addr) { #ifdef INET6 @@ -847,10 +838,11 @@ udp_output(m, va_alist) #ifdef INET6 if (((inp->inp_flags & INP_IPV6) && IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) || - (inp->inp_faddr.s_addr == INADDR_ANY)) { + (inp->inp_faddr.s_addr == INADDR_ANY)) #else /* INET6 */ - if (inp->inp_faddr.s_addr == INADDR_ANY) { + if (inp->inp_faddr.s_addr == INADDR_ANY) #endif /* INET6 */ + { error = ENOTCONN; goto release; } @@ -864,12 +856,6 @@ udp_output(m, va_alist) * Handles IPv4-mapped IPv6 address because temporary connect sets * the right flag. */ - v6packet = ((inp->inp_flags & INP_IPV6) && - !(inp->inp_flags & INP_IPV6_MAPPED)); - - if (!v6packet && control) - m_freem(control); - M_PREPEND(m, v6packet ? (sizeof(struct udphdr) + sizeof(struct ip6_hdr)) : sizeof(struct udpiphdr), M_DONTWAIT); #else /* INET6 */ @@ -971,14 +957,6 @@ udp_output(m, va_alist) uh->uh_ulen = htons(ipv6->ip6_plen); uh->uh_sum = 0; - if (control) { -#if 0 /*XXX*/ - if ((error = ipv6_controltoheader(&m, control, - &forceif, &payload))) - goto release; -#endif - } - /* * Always calculate udp checksum for IPv6 datagrams */ @@ -986,10 +964,10 @@ udp_output(m, va_alist) payload, len + sizeof(struct udphdr)))) uh->uh_sum = 0xffff; - error = ip6_output(m, NULL, &inp->inp_route6, + error = ip6_output(m, inp->inp_outputopts6, &inp->inp_route6, inp->inp_socket->so_options & SO_DONTROUTE, (inp->inp_flags & INP_IPV6_MCAST)?inp->inp_moptions6:NULL, - &forceif); + NULL); } else #endif /* INET6 */ { @@ -1036,17 +1014,19 @@ udp_output(m, va_alist) udpstat.udps_opackets++; #ifdef INET6 - if (inp->inp_flags & INP_IPV6_MCAST) + if (inp->inp_flags & INP_IPV6_MCAST) { error = ip_output(m, inp->inp_options, &inp->inp_route, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), NULL, NULL, inp->inp_socket); - else + } else #endif /* INET6 */ + { error = ip_output(m, inp->inp_options, &inp->inp_route, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), inp->inp_moptions, inp, NULL); + } } bail: @@ -1057,14 +1037,28 @@ bail: if (inp->inp_flags & INP_IPV6) inp->inp_laddr6 = laddr6; else -#endif /* INET6 */ - inp->inp_laddr = laddr; +#endif + inp->inp_laddr = laddr; splx(s); } + if (control) { +#ifdef INET6 + if (v6packet) + inp->inp_outputopts6 = stickyopt; +#endif + m_freem(control); + } return (error); release: m_freem(m); + if (control) { +#ifdef INET6 + if (v6packet) + inp->inp_outputopts6 = stickyopt; +#endif + m_freem(control); + } return (error); } |