[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

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