Annotation of 43BSDReno/sys/netinet/ip_output.c, revision 1.1

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

unix.superglobalmegacorp.com

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