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

unix.superglobalmegacorp.com

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