Annotation of qemu/slirp/ip_input.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1988, 1993
                      3:  *     The Regents of the University of California.  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_input.c  8.2 (Berkeley) 1/4/94
                     34:  * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp
                     35:  */
                     36: 
                     37: /*
                     38:  * Changes and additions relating to SLiRP are
                     39:  * Copyright (c) 1995 Danny Gasparovski.
1.1.1.3 ! root       40:  *
1.1       root       41:  * Please read the file COPYRIGHT for the
                     42:  * terms and conditions of the copyright.
                     43:  */
                     44: 
                     45: #include <slirp.h>
                     46: #include "ip_icmp.h"
                     47: 
1.1.1.3 ! root       48: #ifdef LOG_ENABLED
1.1       root       49: struct ipstat ipstat;
1.1.1.3 ! root       50: #endif
        !            51: 
1.1       root       52: struct ipq ipq;
                     53: 
1.1.1.3 ! root       54: static struct ip *ip_reass(register struct ipasfrag *ip,
        !            55:                            register struct ipq *fp);
        !            56: static void ip_freef(struct ipq *fp);
        !            57: static void ip_enq(register struct ipasfrag *p,
        !            58:                    register struct ipasfrag *prev);
        !            59: static void ip_deq(register struct ipasfrag *p);
        !            60: 
1.1       root       61: /*
                     62:  * IP initialization: fill in IP protocol switch table.
                     63:  * All protocols not implemented in kernel go to raw IP protocol handler.
                     64:  */
                     65: void
                     66: ip_init()
                     67: {
                     68:        ipq.next = ipq.prev = (ipqp_32)&ipq;
                     69:        ip_id = tt.tv_sec & 0xffff;
                     70:        udp_init();
                     71:        tcp_init();
                     72: }
                     73: 
                     74: /*
                     75:  * Ip input routine.  Checksum and byte swap header.  If fragmented
                     76:  * try to reassemble.  Process options.  Pass to next level.
                     77:  */
                     78: void
                     79: ip_input(m)
                     80:        struct mbuf *m;
                     81: {
                     82:        register struct ip *ip;
                     83:        int hlen;
1.1.1.3 ! root       84: 
1.1       root       85:        DEBUG_CALL("ip_input");
                     86:        DEBUG_ARG("m = %lx", (long)m);
                     87:        DEBUG_ARG("m_len = %d", m->m_len);
                     88: 
1.1.1.3 ! root       89:        STAT(ipstat.ips_total++);
        !            90: 
1.1       root       91:        if (m->m_len < sizeof (struct ip)) {
1.1.1.3 ! root       92:                STAT(ipstat.ips_toosmall++);
1.1       root       93:                return;
                     94:        }
1.1.1.3 ! root       95: 
1.1       root       96:        ip = mtod(m, struct ip *);
1.1.1.3 ! root       97: 
1.1       root       98:        if (ip->ip_v != IPVERSION) {
1.1.1.3 ! root       99:                STAT(ipstat.ips_badvers++);
1.1       root      100:                goto bad;
                    101:        }
                    102: 
                    103:        hlen = ip->ip_hl << 2;
                    104:        if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
1.1.1.3 ! root      105:          STAT(ipstat.ips_badhlen++);                     /* or packet too short */
1.1       root      106:          goto bad;
                    107:        }
                    108: 
                    109:         /* keep ip header intact for ICMP reply
1.1.1.3 ! root      110:         * ip->ip_sum = cksum(m, hlen);
        !           111:         * if (ip->ip_sum) {
1.1       root      112:         */
                    113:        if(cksum(m,hlen)) {
1.1.1.3 ! root      114:          STAT(ipstat.ips_badsum++);
1.1       root      115:          goto bad;
                    116:        }
                    117: 
                    118:        /*
                    119:         * Convert fields to host representation.
                    120:         */
                    121:        NTOHS(ip->ip_len);
                    122:        if (ip->ip_len < hlen) {
1.1.1.3 ! root      123:                STAT(ipstat.ips_badlen++);
1.1       root      124:                goto bad;
                    125:        }
                    126:        NTOHS(ip->ip_id);
                    127:        NTOHS(ip->ip_off);
                    128: 
                    129:        /*
                    130:         * Check that the amount of data in the buffers
                    131:         * is as at least much as the IP header would have us expect.
                    132:         * Trim mbufs if longer than we expect.
                    133:         * Drop packet if shorter than we expect.
                    134:         */
                    135:        if (m->m_len < ip->ip_len) {
1.1.1.3 ! root      136:                STAT(ipstat.ips_tooshort++);
1.1       root      137:                goto bad;
                    138:        }
                    139:        /* Should drop packet if mbuf too long? hmmm... */
                    140:        if (m->m_len > ip->ip_len)
                    141:           m_adj(m, ip->ip_len - m->m_len);
                    142: 
                    143:        /* check ip_ttl for a correct ICMP reply */
                    144:        if(ip->ip_ttl==0 || ip->ip_ttl==1) {
                    145:          icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
                    146:          goto bad;
                    147:        }
                    148: 
                    149:        /*
                    150:         * Process options and, if not destined for us,
                    151:         * ship it on.  ip_dooptions returns 1 when an
                    152:         * error was detected (causing an icmp message
                    153:         * to be sent and the original packet to be freed).
                    154:         */
                    155: /* We do no IP options */
                    156: /*     if (hlen > sizeof (struct ip) && ip_dooptions(m))
                    157:  *             goto next;
                    158:  */
                    159:        /*
                    160:         * If offset or IP_MF are set, must reassemble.
                    161:         * Otherwise, nothing need be done.
                    162:         * (We could look in the reassembly queue to see
                    163:         * if the packet was previously fragmented,
                    164:         * but it's not worth the time; just let them time out.)
1.1.1.3 ! root      165:         *
1.1       root      166:         * XXX This should fail, don't fragment yet
                    167:         */
                    168:        if (ip->ip_off &~ IP_DF) {
                    169:          register struct ipq *fp;
                    170:                /*
                    171:                 * Look for queue of fragments
                    172:                 * of this datagram.
                    173:                 */
                    174:                for (fp = (struct ipq *) ipq.next; fp != &ipq;
                    175:                     fp = (struct ipq *) fp->next)
                    176:                  if (ip->ip_id == fp->ipq_id &&
                    177:                      ip->ip_src.s_addr == fp->ipq_src.s_addr &&
                    178:                      ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
                    179:                      ip->ip_p == fp->ipq_p)
                    180:                    goto found;
                    181:                fp = 0;
                    182:        found:
                    183: 
                    184:                /*
                    185:                 * Adjust ip_len to not reflect header,
                    186:                 * set ip_mff if more fragments are expected,
                    187:                 * convert offset of this to bytes.
                    188:                 */
                    189:                ip->ip_len -= hlen;
                    190:                if (ip->ip_off & IP_MF)
                    191:                  ((struct ipasfrag *)ip)->ipf_mff |= 1;
1.1.1.3 ! root      192:                else
1.1       root      193:                  ((struct ipasfrag *)ip)->ipf_mff &= ~1;
                    194: 
                    195:                ip->ip_off <<= 3;
                    196: 
                    197:                /*
                    198:                 * If datagram marked as having more fragments
                    199:                 * or if this is not the first fragment,
                    200:                 * attempt reassembly; if it succeeds, proceed.
                    201:                 */
                    202:                if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
1.1.1.3 ! root      203:                        STAT(ipstat.ips_fragments++);
1.1       root      204:                        ip = ip_reass((struct ipasfrag *)ip, fp);
                    205:                        if (ip == 0)
                    206:                                return;
1.1.1.3 ! root      207:                        STAT(ipstat.ips_reassembled++);
1.1       root      208:                        m = dtom(ip);
                    209:                } else
                    210:                        if (fp)
                    211:                           ip_freef(fp);
                    212: 
                    213:        } else
                    214:                ip->ip_len -= hlen;
                    215: 
                    216:        /*
                    217:         * Switch out to protocol's input routine.
                    218:         */
1.1.1.3 ! root      219:        STAT(ipstat.ips_delivered++);
1.1       root      220:        switch (ip->ip_p) {
                    221:         case IPPROTO_TCP:
                    222:                tcp_input(m, hlen, (struct socket *)NULL);
                    223:                break;
                    224:         case IPPROTO_UDP:
                    225:                udp_input(m, hlen);
                    226:                break;
                    227:         case IPPROTO_ICMP:
                    228:                icmp_input(m, hlen);
                    229:                break;
                    230:         default:
1.1.1.3 ! root      231:                STAT(ipstat.ips_noproto++);
1.1       root      232:                m_free(m);
                    233:        }
                    234:        return;
                    235: bad:
                    236:        m_freem(m);
                    237:        return;
                    238: }
                    239: 
                    240: /*
                    241:  * Take incoming datagram fragment and try to
                    242:  * reassemble it into whole datagram.  If a chain for
                    243:  * reassembly of this datagram already exists, then it
                    244:  * is given as fp; otherwise have to make a chain.
                    245:  */
1.1.1.3 ! root      246: static struct ip *
        !           247: ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
1.1       root      248: {
                    249:        register struct mbuf *m = dtom(ip);
                    250:        register struct ipasfrag *q;
                    251:        int hlen = ip->ip_hl << 2;
                    252:        int i, next;
1.1.1.3 ! root      253: 
1.1       root      254:        DEBUG_CALL("ip_reass");
                    255:        DEBUG_ARG("ip = %lx", (long)ip);
                    256:        DEBUG_ARG("fp = %lx", (long)fp);
                    257:        DEBUG_ARG("m = %lx", (long)m);
                    258: 
                    259:        /*
                    260:         * Presence of header sizes in mbufs
                    261:         * would confuse code below.
                    262:          * Fragment m_data is concatenated.
                    263:         */
                    264:        m->m_data += hlen;
                    265:        m->m_len -= hlen;
                    266: 
                    267:        /*
                    268:         * If first fragment to arrive, create a reassembly queue.
                    269:         */
                    270:        if (fp == 0) {
                    271:          struct mbuf *t;
                    272:          if ((t = m_get()) == NULL) goto dropfrag;
                    273:          fp = mtod(t, struct ipq *);
                    274:          insque_32(fp, &ipq);
                    275:          fp->ipq_ttl = IPFRAGTTL;
                    276:          fp->ipq_p = ip->ip_p;
                    277:          fp->ipq_id = ip->ip_id;
                    278:          fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;
                    279:          fp->ipq_src = ((struct ip *)ip)->ip_src;
                    280:          fp->ipq_dst = ((struct ip *)ip)->ip_dst;
                    281:          q = (struct ipasfrag *)fp;
                    282:          goto insert;
                    283:        }
1.1.1.3 ! root      284: 
1.1       root      285:        /*
                    286:         * Find a segment which begins after this one does.
                    287:         */
                    288:        for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;
                    289:            q = (struct ipasfrag *)q->ipf_next)
                    290:                if (q->ip_off > ip->ip_off)
                    291:                        break;
                    292: 
                    293:        /*
                    294:         * If there is a preceding segment, it may provide some of
                    295:         * our data already.  If so, drop the data from the incoming
                    296:         * segment.  If it provides all of our data, drop us.
                    297:         */
                    298:        if (q->ipf_prev != (ipasfragp_32)fp) {
                    299:                i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +
                    300:                  ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;
                    301:                if (i > 0) {
                    302:                        if (i >= ip->ip_len)
                    303:                                goto dropfrag;
                    304:                        m_adj(dtom(ip), i);
                    305:                        ip->ip_off += i;
                    306:                        ip->ip_len -= i;
                    307:                }
                    308:        }
                    309: 
                    310:        /*
                    311:         * While we overlap succeeding segments trim them or,
                    312:         * if they are completely covered, dequeue them.
                    313:         */
                    314:        while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
                    315:                i = (ip->ip_off + ip->ip_len) - q->ip_off;
                    316:                if (i < q->ip_len) {
                    317:                        q->ip_len -= i;
                    318:                        q->ip_off += i;
                    319:                        m_adj(dtom(q), i);
                    320:                        break;
                    321:                }
                    322:                q = (struct ipasfrag *) q->ipf_next;
                    323:                m_freem(dtom((struct ipasfrag *) q->ipf_prev));
                    324:                ip_deq((struct ipasfrag *) q->ipf_prev);
                    325:        }
                    326: 
                    327: insert:
                    328:        /*
                    329:         * Stick new segment in its place;
                    330:         * check for complete reassembly.
                    331:         */
                    332:        ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
                    333:        next = 0;
                    334:        for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
                    335:             q = (struct ipasfrag *) q->ipf_next) {
                    336:                if (q->ip_off != next)
                    337:                        return (0);
                    338:                next += q->ip_len;
                    339:        }
                    340:        if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
                    341:                return (0);
                    342: 
                    343:        /*
                    344:         * Reassembly is complete; concatenate fragments.
                    345:         */
                    346:        q = (struct ipasfrag *) fp->ipq_next;
                    347:        m = dtom(q);
                    348: 
                    349:        q = (struct ipasfrag *) q->ipf_next;
                    350:        while (q != (struct ipasfrag *)fp) {
                    351:          struct mbuf *t;
                    352:          t = dtom(q);
                    353:          q = (struct ipasfrag *) q->ipf_next;
1.1.1.2   root      354:          m_cat(m, t);
1.1       root      355:        }
                    356: 
                    357:        /*
                    358:         * Create header for new ip packet by
                    359:         * modifying header of first packet;
                    360:         * dequeue and discard fragment reassembly header.
                    361:         * Make header visible.
                    362:         */
                    363:        ip = (struct ipasfrag *) fp->ipq_next;
                    364: 
                    365:        /*
                    366:         * If the fragments concatenated to an mbuf that's
                    367:         * bigger than the total size of the fragment, then and
                    368:         * m_ext buffer was alloced. But fp->ipq_next points to
                    369:         * the old buffer (in the mbuf), so we must point ip
                    370:         * into the new buffer.
                    371:         */
                    372:        if (m->m_flags & M_EXT) {
                    373:          int delta;
                    374:          delta = (char *)ip - m->m_dat;
                    375:          ip = (struct ipasfrag *)(m->m_ext + delta);
                    376:        }
                    377: 
1.1.1.3 ! root      378:        /* DEBUG_ARG("ip = %lx", (long)ip);
1.1       root      379:         * ip=(struct ipasfrag *)m->m_data; */
                    380: 
                    381:        ip->ip_len = next;
                    382:        ip->ipf_mff &= ~1;
                    383:        ((struct ip *)ip)->ip_src = fp->ipq_src;
                    384:        ((struct ip *)ip)->ip_dst = fp->ipq_dst;
                    385:        remque_32(fp);
                    386:        (void) m_free(dtom(fp));
                    387:        m = dtom(ip);
                    388:        m->m_len += (ip->ip_hl << 2);
                    389:        m->m_data -= (ip->ip_hl << 2);
                    390: 
                    391:        return ((struct ip *)ip);
                    392: 
                    393: dropfrag:
1.1.1.3 ! root      394:        STAT(ipstat.ips_fragdropped++);
1.1       root      395:        m_freem(m);
                    396:        return (0);
                    397: }
                    398: 
                    399: /*
                    400:  * Free a fragment reassembly header and all
                    401:  * associated datagrams.
                    402:  */
1.1.1.3 ! root      403: static void
        !           404: ip_freef(struct ipq *fp)
1.1       root      405: {
                    406:        register struct ipasfrag *q, *p;
                    407: 
                    408:        for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
                    409:            q = p) {
                    410:                p = (struct ipasfrag *) q->ipf_next;
                    411:                ip_deq(q);
                    412:                m_freem(dtom(q));
                    413:        }
                    414:        remque_32(fp);
                    415:        (void) m_free(dtom(fp));
                    416: }
                    417: 
                    418: /*
                    419:  * Put an ip fragment on a reassembly chain.
                    420:  * Like insque, but pointers in middle of structure.
                    421:  */
1.1.1.3 ! root      422: static void
        !           423: ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
1.1       root      424: {
                    425:        DEBUG_CALL("ip_enq");
                    426:        DEBUG_ARG("prev = %lx", (long)prev);
                    427:        p->ipf_prev = (ipasfragp_32) prev;
                    428:        p->ipf_next = prev->ipf_next;
                    429:        ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
                    430:        prev->ipf_next = (ipasfragp_32) p;
                    431: }
                    432: 
                    433: /*
                    434:  * To ip_enq as remque is to insque.
                    435:  */
1.1.1.3 ! root      436: static void
        !           437: ip_deq(register struct ipasfrag *p)
1.1       root      438: {
                    439:        ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
                    440:        ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
                    441: }
                    442: 
                    443: /*
                    444:  * IP timer processing;
                    445:  * if a timer expires on a reassembly
                    446:  * queue, discard it.
                    447:  */
                    448: void
                    449: ip_slowtimo()
                    450: {
                    451:        register struct ipq *fp;
1.1.1.3 ! root      452: 
1.1       root      453:        DEBUG_CALL("ip_slowtimo");
1.1.1.3 ! root      454: 
1.1       root      455:        fp = (struct ipq *) ipq.next;
                    456:        if (fp == 0)
                    457:           return;
                    458: 
                    459:        while (fp != &ipq) {
                    460:                --fp->ipq_ttl;
                    461:                fp = (struct ipq *) fp->next;
                    462:                if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
1.1.1.3 ! root      463:                        STAT(ipstat.ips_fragtimeout++);
1.1       root      464:                        ip_freef((struct ipq *) fp->prev);
                    465:                }
                    466:        }
                    467: }
                    468: 
                    469: /*
                    470:  * Do option processing on a datagram,
                    471:  * possibly discarding it if bad options are encountered,
                    472:  * or forwarding it if source-routed.
                    473:  * Returns 1 if packet has been forwarded/freed,
                    474:  * 0 if the packet should be processed further.
                    475:  */
                    476: 
                    477: #ifdef notdef
                    478: 
                    479: int
                    480: ip_dooptions(m)
                    481:        struct mbuf *m;
                    482: {
                    483:        register struct ip *ip = mtod(m, struct ip *);
                    484:        register u_char *cp;
                    485:        register struct ip_timestamp *ipt;
                    486:        register struct in_ifaddr *ia;
                    487: /*     int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */
                    488:        int opt, optlen, cnt, off, code, type, forward = 0;
                    489:        struct in_addr *sin, dst;
                    490: typedef u_int32_t n_time;
                    491:        n_time ntime;
                    492: 
                    493:        dst = ip->ip_dst;
                    494:        cp = (u_char *)(ip + 1);
                    495:        cnt = (ip->ip_hl << 2) - sizeof (struct ip);
                    496:        for (; cnt > 0; cnt -= optlen, cp += optlen) {
                    497:                opt = cp[IPOPT_OPTVAL];
                    498:                if (opt == IPOPT_EOL)
                    499:                        break;
                    500:                if (opt == IPOPT_NOP)
                    501:                        optlen = 1;
                    502:                else {
                    503:                        optlen = cp[IPOPT_OLEN];
                    504:                        if (optlen <= 0 || optlen > cnt) {
                    505:                                code = &cp[IPOPT_OLEN] - (u_char *)ip;
                    506:                                goto bad;
                    507:                        }
                    508:                }
                    509:                switch (opt) {
                    510: 
                    511:                default:
                    512:                        break;
                    513: 
                    514:                /*
                    515:                 * Source routing with record.
                    516:                 * Find interface with current destination address.
                    517:                 * If none on this machine then drop if strictly routed,
                    518:                 * or do nothing if loosely routed.
                    519:                 * Record interface address and bring up next address
                    520:                 * component.  If strictly routed make sure next
                    521:                 * address is on directly accessible net.
                    522:                 */
                    523:                case IPOPT_LSRR:
                    524:                case IPOPT_SSRR:
                    525:                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
                    526:                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
                    527:                                goto bad;
                    528:                        }
                    529:                        ipaddr.sin_addr = ip->ip_dst;
                    530:                        ia = (struct in_ifaddr *)
                    531:                                ifa_ifwithaddr((struct sockaddr *)&ipaddr);
                    532:                        if (ia == 0) {
                    533:                                if (opt == IPOPT_SSRR) {
                    534:                                        type = ICMP_UNREACH;
                    535:                                        code = ICMP_UNREACH_SRCFAIL;
                    536:                                        goto bad;
                    537:                                }
                    538:                                /*
                    539:                                 * Loose routing, and not at next destination
                    540:                                 * yet; nothing to do except forward.
                    541:                                 */
                    542:                                break;
                    543:                        }
                    544:                        off--;                  / * 0 origin *  /
                    545:                        if (off > optlen - sizeof(struct in_addr)) {
                    546:                                /*
                    547:                                 * End of source route.  Should be for us.
                    548:                                 */
                    549:                                save_rte(cp, ip->ip_src);
                    550:                                break;
                    551:                        }
                    552:                        /*
                    553:                         * locate outgoing interface
                    554:                         */
                    555:                        bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
                    556:                            sizeof(ipaddr.sin_addr));
                    557:                        if (opt == IPOPT_SSRR) {
                    558: #define        INA     struct in_ifaddr *
                    559: #define        SA      struct sockaddr *
                    560:                            if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
                    561:                                ia = (INA)ifa_ifwithnet((SA)&ipaddr);
                    562:                        } else
                    563:                                ia = ip_rtaddr(ipaddr.sin_addr);
                    564:                        if (ia == 0) {
                    565:                                type = ICMP_UNREACH;
                    566:                                code = ICMP_UNREACH_SRCFAIL;
                    567:                                goto bad;
                    568:                        }
                    569:                        ip->ip_dst = ipaddr.sin_addr;
                    570:                        bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
                    571:                            (caddr_t)(cp + off), sizeof(struct in_addr));
                    572:                        cp[IPOPT_OFFSET] += sizeof(struct in_addr);
                    573:                        /*
                    574:                         * Let ip_intr's mcast routing check handle mcast pkts
                    575:                         */
                    576:                        forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
                    577:                        break;
                    578: 
                    579:                case IPOPT_RR:
                    580:                        if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
                    581:                                code = &cp[IPOPT_OFFSET] - (u_char *)ip;
                    582:                                goto bad;
                    583:                        }
                    584:                        /*
                    585:                         * If no space remains, ignore.
                    586:                         */
                    587:                        off--;                   * 0 origin *
                    588:                        if (off > optlen - sizeof(struct in_addr))
                    589:                                break;
                    590:                        bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
                    591:                            sizeof(ipaddr.sin_addr));
                    592:                        /*
                    593:                         * locate outgoing interface; if we're the destination,
                    594:                         * use the incoming interface (should be same).
                    595:                         */
                    596:                        if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
                    597:                            (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
                    598:                                type = ICMP_UNREACH;
                    599:                                code = ICMP_UNREACH_HOST;
                    600:                                goto bad;
                    601:                        }
                    602:                        bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
                    603:                            (caddr_t)(cp + off), sizeof(struct in_addr));
                    604:                        cp[IPOPT_OFFSET] += sizeof(struct in_addr);
                    605:                        break;
                    606: 
                    607:                case IPOPT_TS:
                    608:                        code = cp - (u_char *)ip;
                    609:                        ipt = (struct ip_timestamp *)cp;
                    610:                        if (ipt->ipt_len < 5)
                    611:                                goto bad;
                    612:                        if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
                    613:                                if (++ipt->ipt_oflw == 0)
                    614:                                        goto bad;
                    615:                                break;
                    616:                        }
                    617:                        sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
                    618:                        switch (ipt->ipt_flg) {
                    619: 
                    620:                        case IPOPT_TS_TSONLY:
                    621:                                break;
                    622: 
                    623:                        case IPOPT_TS_TSANDADDR:
                    624:                                if (ipt->ipt_ptr + sizeof(n_time) +
                    625:                                    sizeof(struct in_addr) > ipt->ipt_len)
                    626:                                        goto bad;
                    627:                                ipaddr.sin_addr = dst;
                    628:                                ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,
                    629:                                                            m->m_pkthdr.rcvif);
                    630:                                if (ia == 0)
                    631:                                        continue;
                    632:                                bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
                    633:                                    (caddr_t)sin, sizeof(struct in_addr));
                    634:                                ipt->ipt_ptr += sizeof(struct in_addr);
                    635:                                break;
                    636: 
                    637:                        case IPOPT_TS_PRESPEC:
                    638:                                if (ipt->ipt_ptr + sizeof(n_time) +
                    639:                                    sizeof(struct in_addr) > ipt->ipt_len)
                    640:                                        goto bad;
                    641:                                bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
                    642:                                    sizeof(struct in_addr));
                    643:                                if (ifa_ifwithaddr((SA)&ipaddr) == 0)
                    644:                                        continue;
                    645:                                ipt->ipt_ptr += sizeof(struct in_addr);
                    646:                                break;
                    647: 
                    648:                        default:
                    649:                                goto bad;
                    650:                        }
                    651:                        ntime = iptime();
                    652:                        bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
                    653:                            sizeof(n_time));
                    654:                        ipt->ipt_ptr += sizeof(n_time);
                    655:                }
                    656:        }
                    657:        if (forward) {
                    658:                ip_forward(m, 1);
                    659:                return (1);
                    660:        }
                    661:                }
                    662:        }
                    663:        return (0);
                    664: bad:
                    665:        /* ip->ip_len -= ip->ip_hl << 2;   XXX icmp_error adds in hdr length */
                    666: 
                    667: /* Not yet */
                    668:        icmp_error(m, type, code, 0, 0);
                    669: 
1.1.1.3 ! root      670:        STAT(ipstat.ips_badoptions++);
1.1       root      671:        return (1);
                    672: }
                    673: 
                    674: #endif /* notdef */
                    675: 
                    676: /*
                    677:  * Strip out IP options, at higher
                    678:  * level protocol in the kernel.
                    679:  * Second argument is buffer to which options
                    680:  * will be moved, and return value is their length.
                    681:  * (XXX) should be deleted; last arg currently ignored.
                    682:  */
                    683: void
                    684: ip_stripoptions(m, mopt)
                    685:        register struct mbuf *m;
                    686:        struct mbuf *mopt;
                    687: {
                    688:        register int i;
                    689:        struct ip *ip = mtod(m, struct ip *);
                    690:        register caddr_t opts;
                    691:        int olen;
                    692: 
                    693:        olen = (ip->ip_hl<<2) - sizeof (struct ip);
                    694:        opts = (caddr_t)(ip + 1);
                    695:        i = m->m_len - (sizeof (struct ip) + olen);
                    696:        memcpy(opts, opts  + olen, (unsigned)i);
                    697:        m->m_len -= olen;
1.1.1.3 ! root      698: 
1.1       root      699:        ip->ip_hl = sizeof(struct ip) >> 2;
                    700: }

unix.superglobalmegacorp.com

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