[BACK]Return to udp6_output.c CVS log [TXT][DIR] Up to [local] / sys / netinet6

Annotation of sys/netinet6/udp6_output.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: udp6_output.c,v 1.14 2007/06/01 00:52:39 henning Exp $        */
        !             2: /*     $KAME: udp6_output.c,v 1.21 2001/02/07 11:51:54 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:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. Neither the name of the project nor the names of its contributors
        !            17:  *    may be used to endorse or promote products derived from this software
        !            18:  *    without specific prior written permission.
        !            19:  *
        !            20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
        !            21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
        !            24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            30:  * SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: /*
        !            34:  * Copyright (c) 1982, 1986, 1989, 1993
        !            35:  *     The Regents of the University of California.  All rights reserved.
        !            36:  *
        !            37:  * Redistribution and use in source and binary forms, with or without
        !            38:  * modification, are permitted provided that the following conditions
        !            39:  * are met:
        !            40:  * 1. Redistributions of source code must retain the above copyright
        !            41:  *    notice, this list of conditions and the following disclaimer.
        !            42:  * 2. Redistributions in binary form must reproduce the above copyright
        !            43:  *    notice, this list of conditions and the following disclaimer in the
        !            44:  *    documentation and/or other materials provided with the distribution.
        !            45:  * 3. Neither the name of the University nor the names of its contributors
        !            46:  *    may be used to endorse or promote products derived from this software
        !            47:  *    without specific prior written permission.
        !            48:  *
        !            49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            59:  * SUCH DAMAGE.
        !            60:  *
        !            61:  *     @(#)udp_var.h   8.1 (Berkeley) 6/10/93
        !            62:  */
        !            63:
        !            64: #include <sys/param.h>
        !            65: #include <sys/malloc.h>
        !            66: #include <sys/mbuf.h>
        !            67: #include <sys/protosw.h>
        !            68: #include <sys/socket.h>
        !            69: #include <sys/socketvar.h>
        !            70: #include <sys/errno.h>
        !            71: #include <sys/stat.h>
        !            72: #include <sys/systm.h>
        !            73: #include <sys/proc.h>
        !            74: #include <sys/syslog.h>
        !            75:
        !            76: #include <net/if.h>
        !            77: #include <net/route.h>
        !            78: #include <net/if_types.h>
        !            79:
        !            80: #include <netinet/in.h>
        !            81: #include <netinet/in_var.h>
        !            82: #include <netinet/in_systm.h>
        !            83: #include <netinet/ip.h>
        !            84: #include <netinet/ip_var.h>
        !            85: #include <netinet/in_pcb.h>
        !            86: #include <netinet/udp.h>
        !            87: #include <netinet/udp_var.h>
        !            88: #include <netinet/ip6.h>
        !            89: #include <netinet6/ip6_var.h>
        !            90: #include <netinet/icmp6.h>
        !            91: #include <netinet6/ip6protosw.h>
        !            92:
        !            93: #include "faith.h"
        !            94:
        !            95: /*
        !            96:  * UDP protocol inplementation.
        !            97:  * Per RFC 768, August, 1980.
        !            98:  */
        !            99:
        !           100: #define in6pcb         inpcb
        !           101: #define in6p_outputopts        inp_outputopts6
        !           102: #define in6p_socket    inp_socket
        !           103: #define in6p_faddr     inp_faddr6
        !           104: #define in6p_laddr     inp_laddr6
        !           105: #define in6p_fport     inp_fport
        !           106: #define in6p_lport     inp_lport
        !           107: #define in6p_flags     inp_flags
        !           108: #define in6p_moptions  inp_moptions6
        !           109: #define in6p_route     inp_route6
        !           110: #define in6p_flowinfo  inp_flowinfo
        !           111: #define udp6stat       udpstat
        !           112: #define udp6s_opackets udps_opackets
        !           113:
        !           114: int
        !           115: udp6_output(in6p, m, addr6, control)
        !           116:        struct in6pcb *in6p;
        !           117:        struct mbuf *m;
        !           118:        struct mbuf *addr6, *control;
        !           119: {
        !           120:        u_int32_t ulen = m->m_pkthdr.len;
        !           121:        u_int32_t plen = sizeof(struct udphdr) + ulen;
        !           122:        struct ip6_hdr *ip6;
        !           123:        struct udphdr *udp6;
        !           124:        struct  in6_addr *laddr, *faddr;
        !           125:        u_short fport;
        !           126:        int error = 0;
        !           127:        struct ip6_pktopts *optp, opt;
        !           128:        int priv;
        !           129:        int af, hlen;
        !           130:        int flags;
        !           131:        struct sockaddr_in6 tmp;
        !           132:        struct proc *p = curproc;       /* XXX */
        !           133:
        !           134:        priv = 0;
        !           135:        if ((in6p->in6p_socket->so_state & SS_PRIV) != 0)
        !           136:                priv = 1;
        !           137:        if (control) {
        !           138:                if ((error = ip6_setpktopts(control, &opt,
        !           139:                    in6p->in6p_outputopts, priv, IPPROTO_UDP)) != 0)
        !           140:                        goto release;
        !           141:                optp = &opt;
        !           142:        } else
        !           143:                optp = in6p->in6p_outputopts;
        !           144:
        !           145:        if (addr6) {
        !           146:                /*
        !           147:                 * IPv4 version of udp_output calls in_pcbconnect in this case,
        !           148:                 * which needs splnet and affects performance.
        !           149:                 * Since we saw no essential reason for calling in_pcbconnect,
        !           150:                 * we get rid of such kind of logic, and call in6_selectsrc
        !           151:                 * and in6_pcbsetport in order to fill in the local address
        !           152:                 * and the local port.
        !           153:                 */
        !           154:                struct sockaddr_in6 *sin6 = mtod(addr6, struct sockaddr_in6 *);
        !           155:
        !           156:                if (addr6->m_len != sizeof(*sin6)) {
        !           157:                        error = EINVAL;
        !           158:                        goto release;
        !           159:                }
        !           160:                if (sin6->sin6_family != AF_INET6) {
        !           161:                        error = EAFNOSUPPORT;
        !           162:                        goto release;
        !           163:                }
        !           164:                if (sin6->sin6_port == 0) {
        !           165:                        error = EADDRNOTAVAIL;
        !           166:                        goto release;
        !           167:                }
        !           168:
        !           169:                if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
        !           170:                        error = EISCONN;
        !           171:                        goto release;
        !           172:                }
        !           173:
        !           174:                /* protect *sin6 from overwrites */
        !           175:                tmp = *sin6;
        !           176:                sin6 = &tmp;
        !           177:
        !           178:                faddr = &sin6->sin6_addr;
        !           179:                fport = sin6->sin6_port; /* allow 0 port */
        !           180:
        !           181:                /* KAME hack: embed scopeid */
        !           182:                if (in6_embedscope(&sin6->sin6_addr, sin6, in6p, NULL) != 0) {
        !           183:                        error = EINVAL;
        !           184:                        goto release;
        !           185:                }
        !           186:
        !           187:                if (1)  /* we don't support IPv4 mapped address */
        !           188:                {
        !           189:                        laddr = in6_selectsrc(sin6, optp,
        !           190:                                              in6p->in6p_moptions,
        !           191:                                              &in6p->in6p_route,
        !           192:                                              &in6p->in6p_laddr, &error);
        !           193:                } else
        !           194:                        laddr = &in6p->in6p_laddr;      /*XXX*/
        !           195:                if (laddr == NULL) {
        !           196:                        if (error == 0)
        !           197:                                error = EADDRNOTAVAIL;
        !           198:                        goto release;
        !           199:                }
        !           200:                if (in6p->in6p_lport == 0 &&
        !           201:                    (error = in6_pcbsetport(laddr, in6p, p)) != 0)
        !           202:                        goto release;
        !           203:        } else {
        !           204:                if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
        !           205:                        error = ENOTCONN;
        !           206:                        goto release;
        !           207:                }
        !           208:                laddr = &in6p->in6p_laddr;
        !           209:                faddr = &in6p->in6p_faddr;
        !           210:                fport = in6p->in6p_fport;
        !           211:        }
        !           212:
        !           213:        if (1)  /* we don't support IPv4 mapped address */
        !           214:        {
        !           215:                af = AF_INET6;
        !           216:                hlen = sizeof(struct ip6_hdr);
        !           217:        } else {
        !           218:                af = AF_INET;
        !           219:                hlen = sizeof(struct ip);
        !           220:        }
        !           221:
        !           222:        /*
        !           223:         * Calculate data length and get a mbuf
        !           224:         * for UDP and IP6 headers.
        !           225:         */
        !           226:        M_PREPEND(m, hlen + sizeof(struct udphdr), M_DONTWAIT);
        !           227:        if (m == 0) {
        !           228:                error = ENOBUFS;
        !           229:                goto release;
        !           230:        }
        !           231:
        !           232:        /*
        !           233:         * Stuff checksum and output datagram.
        !           234:         */
        !           235:        udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
        !           236:        udp6->uh_sport = in6p->in6p_lport; /* lport is always set in the PCB */
        !           237:        udp6->uh_dport = fport;
        !           238:        if (plen <= 0xffff)
        !           239:                udp6->uh_ulen = htons((u_short)plen);
        !           240:        else
        !           241:                udp6->uh_ulen = 0;
        !           242:        udp6->uh_sum = 0;
        !           243:
        !           244:        switch (af) {
        !           245:        case AF_INET6:
        !           246:                ip6 = mtod(m, struct ip6_hdr *);
        !           247:                ip6->ip6_flow   = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
        !           248:                ip6->ip6_vfc    &= ~IPV6_VERSION_MASK;
        !           249:                ip6->ip6_vfc    |= IPV6_VERSION;
        !           250: #if 0                          /* ip6_plen will be filled in ip6_output. */
        !           251:                ip6->ip6_plen   = htons((u_short)plen);
        !           252: #endif
        !           253:                ip6->ip6_nxt    = IPPROTO_UDP;
        !           254:                ip6->ip6_hlim   = in6_selecthlim(in6p,
        !           255:                                                 in6p->in6p_route.ro_rt ?
        !           256:                                                 in6p->in6p_route.ro_rt->rt_ifp : NULL);
        !           257:                ip6->ip6_src    = *laddr;
        !           258:                ip6->ip6_dst    = *faddr;
        !           259:
        !           260:                if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
        !           261:                                sizeof(struct ip6_hdr), plen)) == 0) {
        !           262:                        udp6->uh_sum = 0xffff;
        !           263:                }
        !           264:
        !           265:                flags = 0;
        !           266:                if (in6p->in6p_flags & IN6P_MINMTU)
        !           267:                        flags |= IPV6_MINMTU;
        !           268:
        !           269:                udp6stat.udp6s_opackets++;
        !           270:                error = ip6_output(m, optp, &in6p->in6p_route,
        !           271:                            flags, in6p->in6p_moptions, NULL, in6p);
        !           272:                break;
        !           273:        case AF_INET:
        !           274:                error = EAFNOSUPPORT;
        !           275:                goto release;
        !           276:        }
        !           277:        goto releaseopt;
        !           278:
        !           279: release:
        !           280:        m_freem(m);
        !           281:
        !           282: releaseopt:
        !           283:        if (control) {
        !           284:                ip6_clearpktopts(&opt, -1);
        !           285:                m_freem(control);
        !           286:        }
        !           287:        return (error);
        !           288: }

CVSweb