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

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

unix.superglobalmegacorp.com