Annotation of Net2/netinet/ip_output.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
                      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
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
1.1.1.2 ! root       33:  *     from: @(#)ip_output.c   7.23 (Berkeley) 11/12/90
        !            34:  *     ip_output.c,v 1.3 1993/05/22 11:42:35 cgd Exp
1.1       root       35:  */
                     36: 
                     37: #include "param.h"
                     38: #include "malloc.h"
                     39: #include "mbuf.h"
                     40: #include "errno.h"
                     41: #include "protosw.h"
                     42: #include "socket.h"
                     43: #include "socketvar.h"
                     44: 
                     45: #include "../net/if.h"
                     46: #include "../net/route.h"
                     47: 
                     48: #include "in.h"
                     49: #include "in_systm.h"
                     50: #include "ip.h"
                     51: #include "in_pcb.h"
                     52: #include "in_var.h"
                     53: #include "ip_var.h"
                     54: 
                     55: #ifdef vax
                     56: #include "machine/mtpr.h"
                     57: #endif
                     58: 
                     59: struct mbuf *ip_insertoptions();
                     60: 
                     61: /*
                     62:  * IP output.  The packet in mbuf chain m contains a skeletal IP
                     63:  * header (with len, off, ttl, proto, tos, src, dst).
                     64:  * The mbuf chain containing the packet will be freed.
                     65:  * The mbuf opt, if present, will not be freed.
                     66:  */
                     67: ip_output(m0, opt, ro, flags)
                     68:        struct mbuf *m0;
                     69:        struct mbuf *opt;
                     70:        struct route *ro;
                     71:        int flags;
                     72: {
                     73:        register struct ip *ip, *mhip;
                     74:        register struct ifnet *ifp;
                     75:        register struct mbuf *m = m0;
                     76:        register int hlen = sizeof (struct ip);
                     77:        int len, off, error = 0;
                     78:        struct route iproute;
                     79:        struct sockaddr_in *dst;
                     80:        struct in_ifaddr *ia;
                     81: 
                     82: #ifdef DIAGNOSTIC
                     83:        if ((m->m_flags & M_PKTHDR) == 0)
                     84:                panic("ip_output no HDR");
                     85: #endif
                     86:        if (opt) {
                     87:                m = ip_insertoptions(m, opt, &len);
                     88:                hlen = len;
                     89:        }
                     90:        ip = mtod(m, struct ip *);
                     91:        /*
                     92:         * Fill in IP header.
                     93:         */
                     94:        if ((flags & IP_FORWARDING) == 0) {
                     95:                ip->ip_v = IPVERSION;
                     96:                ip->ip_off &= IP_DF;
                     97:                ip->ip_id = htons(ip_id++);
                     98:                ip->ip_hl = hlen >> 2;
                     99:        } else {
                    100:                hlen = ip->ip_hl << 2;
                    101:                ipstat.ips_localout++;
                    102:        }
                    103:        /*
                    104:         * Route packet.
                    105:         */
                    106:        if (ro == 0) {
                    107:                ro = &iproute;
                    108:                bzero((caddr_t)ro, sizeof (*ro));
                    109:        }
                    110:        dst = (struct sockaddr_in *)&ro->ro_dst;
                    111:        /*
                    112:         * If there is a cached route,
                    113:         * check that it is to the same destination
                    114:         * and is still up.  If not, free it and try again.
                    115:         */
                    116:        if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
                    117:           dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
                    118:                RTFREE(ro->ro_rt);
                    119:                ro->ro_rt = (struct rtentry *)0;
                    120:        }
                    121:        if (ro->ro_rt == 0) {
                    122:                dst->sin_family = AF_INET;
                    123:                dst->sin_len = sizeof(*dst);
                    124:                dst->sin_addr = ip->ip_dst;
                    125:        }
                    126:        /*
                    127:         * If routing to interface only,
                    128:         * short circuit routing lookup.
                    129:         */
                    130:        if (flags & IP_ROUTETOIF) {
                    131: 
                    132:                ia = (struct in_ifaddr *)ifa_ifwithdstaddr((struct sockaddr *)dst);
                    133:                if (ia == 0)
                    134:                        ia = in_iaonnetof(in_netof(ip->ip_dst));
                    135:                if (ia == 0) {
                    136:                        error = ENETUNREACH;
                    137:                        goto bad;
                    138:                }
                    139:                ifp = ia->ia_ifp;
                    140:        } else {
                    141:                if (ro->ro_rt == 0)
                    142:                        rtalloc(ro);
                    143:                if (ro->ro_rt == 0) {
                    144:                        error = EHOSTUNREACH;
                    145:                        goto bad;
                    146:                }
                    147:                ia = (struct in_ifaddr *)ro->ro_rt->rt_ifa;
                    148:                ifp = ro->ro_rt->rt_ifp;
                    149:                ro->ro_rt->rt_use++;
                    150:                if (ro->ro_rt->rt_flags & RTF_GATEWAY)
                    151:                        dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
                    152:        }
                    153: #ifndef notdef
                    154:        /*
                    155:         * If source address not specified yet, use address
                    156:         * of outgoing interface.
                    157:         */
                    158:        if (ip->ip_src.s_addr == INADDR_ANY)
                    159:                ip->ip_src = IA_SIN(ia)->sin_addr;
                    160: #endif
                    161:        /*
                    162:         * Look for broadcast address and
                    163:         * and verify user is allowed to send
                    164:         * such a packet.
                    165:         */
                    166:        if (in_broadcast(dst->sin_addr)) {
                    167:                if ((ifp->if_flags & IFF_BROADCAST) == 0) {
                    168:                        error = EADDRNOTAVAIL;
                    169:                        goto bad;
                    170:                }
                    171:                if ((flags & IP_ALLOWBROADCAST) == 0) {
                    172:                        error = EACCES;
                    173:                        goto bad;
                    174:                }
                    175:                /* don't allow broadcast messages to be fragmented */
                    176:                if ((u_short)ip->ip_len > ifp->if_mtu) {
                    177:                        error = EMSGSIZE;
                    178:                        goto bad;
                    179:                }
                    180:                m->m_flags |= M_BCAST;
                    181:        }
                    182: 
                    183:        /*
                    184:         * If small enough for interface, can just send directly.
                    185:         */
                    186:        if ((u_short)ip->ip_len <= ifp->if_mtu) {
                    187:                ip->ip_len = htons((u_short)ip->ip_len);
                    188:                ip->ip_off = htons((u_short)ip->ip_off);
                    189:                ip->ip_sum = 0;
                    190:                ip->ip_sum = in_cksum(m, hlen);
                    191:                error = (*ifp->if_output)(ifp, m,
                    192:                                (struct sockaddr *)dst, ro->ro_rt);
                    193:                goto done;
                    194:        }
                    195:        ipstat.ips_fragmented++;
                    196:        /*
                    197:         * Too large for interface; fragment if possible.
                    198:         * Must be able to put at least 8 bytes per fragment.
                    199:         */
                    200:        if (ip->ip_off & IP_DF) {
                    201:                error = EMSGSIZE;
                    202:                goto bad;
                    203:        }
                    204:        len = (ifp->if_mtu - hlen) &~ 7;
                    205:        if (len < 8) {
                    206:                error = EMSGSIZE;
                    207:                goto bad;
                    208:        }
                    209: 
                    210:     {
                    211:        int mhlen, firstlen = len;
                    212:        struct mbuf **mnext = &m->m_nextpkt;
                    213: 
                    214:        /*
                    215:         * Loop through length of segment after first fragment,
                    216:         * make new header and copy data of each part and link onto chain.
                    217:         */
                    218:        m0 = m;
                    219:        mhlen = sizeof (struct ip);
                    220:        for (off = hlen + len; off < (u_short)ip->ip_len; off += len) {
                    221:                MGETHDR(m, M_DONTWAIT, MT_HEADER);
                    222:                if (m == 0) {
                    223:                        error = ENOBUFS;
                    224:                        goto sendorfree;
                    225:                }
                    226:                m->m_data += max_linkhdr;
                    227:                mhip = mtod(m, struct ip *);
                    228:                *mhip = *ip;
                    229:                if (hlen > sizeof (struct ip)) {
                    230:                        mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
                    231:                        mhip->ip_hl = mhlen >> 2;
                    232:                }
                    233:                m->m_len = mhlen;
                    234:                mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
                    235:                if (ip->ip_off & IP_MF)
                    236:                        mhip->ip_off |= IP_MF;
                    237:                if (off + len >= (u_short)ip->ip_len)
                    238:                        len = (u_short)ip->ip_len - off;
                    239:                else
                    240:                        mhip->ip_off |= IP_MF;
                    241:                mhip->ip_len = htons((u_short)(len + mhlen));
                    242:                m->m_next = m_copy(m0, off, len);
                    243:                if (m->m_next == 0) {
                    244:                        error = ENOBUFS;        /* ??? */
                    245:                        goto sendorfree;
                    246:                }
                    247:                m->m_pkthdr.len = mhlen + len;
                    248:                m->m_pkthdr.rcvif = (struct ifnet *)0;
                    249:                mhip->ip_off = htons((u_short)mhip->ip_off);
                    250:                mhip->ip_sum = 0;
                    251:                mhip->ip_sum = in_cksum(m, mhlen);
                    252:                *mnext = m;
                    253:                mnext = &m->m_nextpkt;
                    254:                ipstat.ips_ofragments++;
                    255:        }
                    256:        /*
                    257:         * Update first fragment by trimming what's been copied out
                    258:         * and updating header, then send each fragment (in order).
                    259:         */
                    260:        m = m0;
                    261:        m_adj(m, hlen + firstlen - (u_short)ip->ip_len);
                    262:        m->m_pkthdr.len = hlen + firstlen;
                    263:        ip->ip_len = htons((u_short)m->m_pkthdr.len);
                    264:        ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
                    265:        ip->ip_sum = 0;
                    266:        ip->ip_sum = in_cksum(m, hlen);
                    267: sendorfree:
                    268:        for (m = m0; m; m = m0) {
                    269:                m0 = m->m_nextpkt;
                    270:                m->m_nextpkt = 0;
                    271:                if (error == 0)
                    272:                        error = (*ifp->if_output)(ifp, m,
                    273:                            (struct sockaddr *)dst, ro->ro_rt);
                    274:                else
                    275:                        m_freem(m);
                    276:        }
                    277:     }
                    278: done:
                    279:        if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt)
                    280:                RTFREE(ro->ro_rt);
                    281:        return (error);
                    282: bad:
                    283:        m_freem(m0);
                    284:        goto done;
                    285: }
                    286: 
                    287: /*
                    288:  * Insert IP options into preformed packet.
                    289:  * Adjust IP destination as required for IP source routing,
                    290:  * as indicated by a non-zero in_addr at the start of the options.
                    291:  */
                    292: struct mbuf *
                    293: ip_insertoptions(m, opt, phlen)
                    294:        register struct mbuf *m;
                    295:        struct mbuf *opt;
                    296:        int *phlen;
                    297: {
                    298:        register struct ipoption *p = mtod(opt, struct ipoption *);
                    299:        struct mbuf *n;
                    300:        register struct ip *ip = mtod(m, struct ip *);
                    301:        unsigned optlen;
                    302: 
                    303:        optlen = opt->m_len - sizeof(p->ipopt_dst);
                    304:        if (optlen + (u_short)ip->ip_len > IP_MAXPACKET)
                    305:                return (m);             /* XXX should fail */
                    306:        if (p->ipopt_dst.s_addr)
                    307:                ip->ip_dst = p->ipopt_dst;
                    308:        if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
                    309:                MGETHDR(n, M_DONTWAIT, MT_HEADER);
                    310:                if (n == 0)
                    311:                        return (m);
                    312:                n->m_pkthdr.len = m->m_pkthdr.len + optlen;
                    313:                m->m_len -= sizeof(struct ip);
                    314:                m->m_data += sizeof(struct ip);
                    315:                n->m_next = m;
                    316:                m = n;
                    317:                m->m_len = optlen + sizeof(struct ip);
                    318:                m->m_data += max_linkhdr;
                    319:                bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
                    320:        } else {
                    321:                m->m_data -= optlen;
                    322:                m->m_len += optlen;
                    323:                m->m_pkthdr.len += optlen;
                    324:                ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
                    325:        }
                    326:        ip = mtod(m, struct ip *);
                    327:        bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen);
                    328:        *phlen = sizeof(struct ip) + optlen;
                    329:        ip->ip_len += optlen;
                    330:        return (m);
                    331: }
                    332: 
                    333: /*
                    334:  * Copy options from ip to jp,
                    335:  * omitting those not copied during fragmentation.
                    336:  */
                    337: ip_optcopy(ip, jp)
                    338:        struct ip *ip, *jp;
                    339: {
                    340:        register u_char *cp, *dp;
                    341:        int opt, optlen, cnt;
                    342: 
                    343:        cp = (u_char *)(ip + 1);
                    344:        dp = (u_char *)(jp + 1);
                    345:        cnt = (ip->ip_hl << 2) - sizeof (struct ip);
                    346:        for (; cnt > 0; cnt -= optlen, cp += optlen) {
                    347:                opt = cp[0];
                    348:                if (opt == IPOPT_EOL)
                    349:                        break;
                    350:                if (opt == IPOPT_NOP)
                    351:                        optlen = 1;
                    352:                else
                    353:                        optlen = cp[IPOPT_OLEN];
                    354:                /* bogus lengths should have been caught by ip_dooptions */
                    355:                if (optlen > cnt)
                    356:                        optlen = cnt;
                    357:                if (IPOPT_COPIED(opt)) {
                    358:                        bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen);
                    359:                        dp += optlen;
                    360:                }
                    361:        }
                    362:        for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
                    363:                *dp++ = IPOPT_EOL;
                    364:        return (optlen);
                    365: }
                    366: 
                    367: /*
                    368:  * IP socket option processing.
                    369:  */
                    370: ip_ctloutput(op, so, level, optname, mp)
                    371:        int op;
                    372:        struct socket *so;
                    373:        int level, optname;
                    374:        struct mbuf **mp;
                    375: {
                    376:        register struct inpcb *inp = sotoinpcb(so);
                    377:        register struct mbuf *m = *mp;
                    378:        register int optval;
                    379:        int error = 0;
                    380: 
                    381:        if (level != IPPROTO_IP)
                    382:                error = EINVAL;
                    383:        else switch (op) {
                    384: 
                    385:        case PRCO_SETOPT:
                    386:                switch (optname) {
                    387:                case IP_OPTIONS:
                    388: #ifdef notyet
                    389:                case IP_RETOPTS:
                    390:                        return (ip_pcbopts(optname, &inp->inp_options, m));
                    391: #else
                    392:                        return (ip_pcbopts(&inp->inp_options, m));
                    393: #endif
                    394: 
                    395:                case IP_TOS:
                    396:                case IP_TTL:
                    397:                case IP_RECVOPTS:
                    398:                case IP_RECVRETOPTS:
                    399:                case IP_RECVDSTADDR:
                    400:                        if (m->m_len != sizeof(int))
                    401:                                error = EINVAL;
                    402:                        else {
                    403:                                optval = *mtod(m, int *);
                    404:                                switch (optname) {
                    405: 
                    406:                                case IP_TOS:
                    407:                                        inp->inp_ip.ip_tos = optval;
                    408:                                        break;
                    409: 
                    410:                                case IP_TTL:
                    411:                                        inp->inp_ip.ip_ttl = optval;
                    412:                                        break;
                    413: #define        OPTSET(bit) \
                    414:        if (optval) \
                    415:                inp->inp_flags |= bit; \
                    416:        else \
                    417:                inp->inp_flags &= ~bit;
                    418: 
                    419:                                case IP_RECVOPTS:
                    420:                                        OPTSET(INP_RECVOPTS);
                    421:                                        break;
                    422: 
                    423:                                case IP_RECVRETOPTS:
                    424:                                        OPTSET(INP_RECVRETOPTS);
                    425:                                        break;
                    426: 
                    427:                                case IP_RECVDSTADDR:
                    428:                                        OPTSET(INP_RECVDSTADDR);
                    429:                                        break;
                    430:                                }
                    431:                        }
                    432:                        break;
                    433: #undef OPTSET
                    434: 
                    435:                default:
                    436:                        error = EINVAL;
                    437:                        break;
                    438:                }
                    439:                if (m)
                    440:                        (void)m_free(m);
                    441:                break;
                    442: 
                    443:        case PRCO_GETOPT:
                    444:                switch (optname) {
                    445:                case IP_OPTIONS:
                    446:                case IP_RETOPTS:
                    447:                        *mp = m = m_get(M_WAIT, MT_SOOPTS);
                    448:                        if (inp->inp_options) {
                    449:                                m->m_len = inp->inp_options->m_len;
                    450:                                bcopy(mtod(inp->inp_options, caddr_t),
                    451:                                    mtod(m, caddr_t), (unsigned)m->m_len);
                    452:                        } else
                    453:                                m->m_len = 0;
                    454:                        break;
                    455: 
                    456:                case IP_TOS:
                    457:                case IP_TTL:
                    458:                case IP_RECVOPTS:
                    459:                case IP_RECVRETOPTS:
                    460:                case IP_RECVDSTADDR:
                    461:                        *mp = m = m_get(M_WAIT, MT_SOOPTS);
                    462:                        m->m_len = sizeof(int);
                    463:                        switch (optname) {
                    464: 
                    465:                        case IP_TOS:
                    466:                                optval = inp->inp_ip.ip_tos;
                    467:                                break;
                    468: 
                    469:                        case IP_TTL:
                    470:                                optval = inp->inp_ip.ip_ttl;
                    471:                                break;
                    472: 
                    473: #define        OPTBIT(bit)     (inp->inp_flags & bit ? 1 : 0)
                    474: 
                    475:                        case IP_RECVOPTS:
                    476:                                optval = OPTBIT(INP_RECVOPTS);
                    477:                                break;
                    478: 
                    479:                        case IP_RECVRETOPTS:
                    480:                                optval = OPTBIT(INP_RECVRETOPTS);
                    481:                                break;
                    482: 
                    483:                        case IP_RECVDSTADDR:
                    484:                                optval = OPTBIT(INP_RECVDSTADDR);
                    485:                                break;
                    486:                        }
                    487:                        *mtod(m, int *) = optval;
                    488:                        break;
                    489: 
                    490:                default:
                    491:                        error = EINVAL;
                    492:                        break;
                    493:                }
                    494:                break;
                    495:        }
                    496:        return (error);
                    497: }
                    498: 
                    499: /*
                    500:  * Set up IP options in pcb for insertion in output packets.
                    501:  * Store in mbuf with pointer in pcbopt, adding pseudo-option
                    502:  * with destination address if source routed.
                    503:  */
                    504: #ifdef notyet
                    505: ip_pcbopts(optname, pcbopt, m)
                    506:        int optname;
                    507: #else
                    508: ip_pcbopts(pcbopt, m)
                    509: #endif
                    510:        struct mbuf **pcbopt;
                    511:        register struct mbuf *m;
                    512: {
                    513:        register cnt, optlen;
                    514:        register u_char *cp;
                    515:        u_char opt;
                    516: 
                    517:        /* turn off any old options */
                    518:        if (*pcbopt)
                    519:                (void)m_free(*pcbopt);
                    520:        *pcbopt = 0;
                    521:        if (m == (struct mbuf *)0 || m->m_len == 0) {
                    522:                /*
                    523:                 * Only turning off any previous options.
                    524:                 */
                    525:                if (m)
                    526:                        (void)m_free(m);
                    527:                return (0);
                    528:        }
                    529: 
                    530: #ifndef        vax
                    531:        if (m->m_len % sizeof(long))
                    532:                goto bad;
                    533: #endif
                    534:        /*
                    535:         * IP first-hop destination address will be stored before
                    536:         * actual options; move other options back
                    537:         * and clear it when none present.
                    538:         */
                    539:        if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
                    540:                goto bad;
                    541:        cnt = m->m_len;
                    542:        m->m_len += sizeof(struct in_addr);
                    543:        cp = mtod(m, u_char *) + sizeof(struct in_addr);
                    544:        ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
                    545:        bzero(mtod(m, caddr_t), sizeof(struct in_addr));
                    546: 
                    547:        for (; cnt > 0; cnt -= optlen, cp += optlen) {
                    548:                opt = cp[IPOPT_OPTVAL];
                    549:                if (opt == IPOPT_EOL)
                    550:                        break;
                    551:                if (opt == IPOPT_NOP)
                    552:                        optlen = 1;
                    553:                else {
                    554:                        optlen = cp[IPOPT_OLEN];
                    555:                        if (optlen <= IPOPT_OLEN || optlen > cnt)
                    556:                                goto bad;
                    557:                }
                    558:                switch (opt) {
                    559: 
                    560:                default:
                    561:                        break;
                    562: 
                    563:                case IPOPT_LSRR:
                    564:                case IPOPT_SSRR:
                    565:                        /*
                    566:                         * user process specifies route as:
                    567:                         *      ->A->B->C->D
                    568:                         * D must be our final destination (but we can't
                    569:                         * check that since we may not have connected yet).
                    570:                         * A is first hop destination, which doesn't appear in
                    571:                         * actual IP option, but is stored before the options.
                    572:                         */
                    573:                        if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
                    574:                                goto bad;
                    575:                        m->m_len -= sizeof(struct in_addr);
                    576:                        cnt -= sizeof(struct in_addr);
                    577:                        optlen -= sizeof(struct in_addr);
                    578:                        cp[IPOPT_OLEN] = optlen;
                    579:                        /*
                    580:                         * Move first hop before start of options.
                    581:                         */
                    582:                        bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
                    583:                            sizeof(struct in_addr));
                    584:                        /*
                    585:                         * Then copy rest of options back
                    586:                         * to close up the deleted entry.
                    587:                         */
                    588:                        ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
                    589:                            sizeof(struct in_addr)),
                    590:                            (caddr_t)&cp[IPOPT_OFFSET+1],
                    591:                            (unsigned)cnt + sizeof(struct in_addr));
                    592:                        break;
                    593:                }
                    594:        }
                    595:        if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
                    596:                goto bad;
                    597:        *pcbopt = m;
                    598:        return (0);
                    599: 
                    600: bad:
                    601:        (void)m_free(m);
                    602:        return (EINVAL);
                    603: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.