|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988, 1990, 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. Neither the name of the University nor the names of its contributors ! 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_output.c 8.3 (Berkeley) 1/21/94 ! 30: * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp ! 31: */ ! 32: ! 33: /* ! 34: * Changes and additions relating to SLiRP are ! 35: * Copyright (c) 1995 Danny Gasparovski. ! 36: * ! 37: * Please read the file COPYRIGHT for the ! 38: * terms and conditions of the copyright. ! 39: */ ! 40: ! 41: #include <slirp.h> ! 42: ! 43: u_int16_t ip_id; ! 44: ! 45: /* ! 46: * IP output. The packet in mbuf chain m contains a skeletal IP ! 47: * header (with len, off, ttl, proto, tos, src, dst). ! 48: * The mbuf chain containing the packet will be freed. ! 49: * The mbuf opt, if present, will not be freed. ! 50: */ ! 51: int ! 52: ip_output(so, m0) ! 53: struct socket *so; ! 54: struct mbuf *m0; ! 55: { ! 56: register struct ip *ip; ! 57: register struct mbuf *m = m0; ! 58: register int hlen = sizeof(struct ip ); ! 59: int len, off, error = 0; ! 60: ! 61: DEBUG_CALL("ip_output"); ! 62: DEBUG_ARG("so = %lx", (long)so); ! 63: DEBUG_ARG("m0 = %lx", (long)m0); ! 64: ! 65: /* We do no options */ ! 66: /* if (opt) { ! 67: * m = ip_insertoptions(m, opt, &len); ! 68: * hlen = len; ! 69: * } ! 70: */ ! 71: ip = mtod(m, struct ip *); ! 72: /* ! 73: * Fill in IP header. ! 74: */ ! 75: ip->ip_v = IPVERSION; ! 76: ip->ip_off &= IP_DF; ! 77: ip->ip_id = htons(ip_id++); ! 78: ip->ip_hl = hlen >> 2; ! 79: ipstat.ips_localout++; ! 80: ! 81: /* ! 82: * Verify that we have any chance at all of being able to queue ! 83: * the packet or packet fragments ! 84: */ ! 85: /* XXX Hmmm... */ ! 86: /* if (if_queued > if_thresh && towrite <= 0) { ! 87: * error = ENOBUFS; ! 88: * goto bad; ! 89: * } ! 90: */ ! 91: ! 92: /* ! 93: * If small enough for interface, can just send directly. ! 94: */ ! 95: if ((u_int16_t)ip->ip_len <= if_mtu) { ! 96: ip->ip_len = htons((u_int16_t)ip->ip_len); ! 97: ip->ip_off = htons((u_int16_t)ip->ip_off); ! 98: ip->ip_sum = 0; ! 99: ip->ip_sum = cksum(m, hlen); ! 100: ! 101: if_output(so, m); ! 102: goto done; ! 103: } ! 104: ! 105: /* ! 106: * Too large for interface; fragment if possible. ! 107: * Must be able to put at least 8 bytes per fragment. ! 108: */ ! 109: if (ip->ip_off & IP_DF) { ! 110: error = -1; ! 111: ipstat.ips_cantfrag++; ! 112: goto bad; ! 113: } ! 114: ! 115: len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ ! 116: if (len < 8) { ! 117: error = -1; ! 118: goto bad; ! 119: } ! 120: ! 121: { ! 122: int mhlen, firstlen = len; ! 123: struct mbuf **mnext = &m->m_nextpkt; ! 124: ! 125: /* ! 126: * Loop through length of segment after first fragment, ! 127: * make new header and copy data of each part and link onto chain. ! 128: */ ! 129: m0 = m; ! 130: mhlen = sizeof (struct ip); ! 131: for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { ! 132: register struct ip *mhip; ! 133: m = m_get(); ! 134: if (m == 0) { ! 135: error = -1; ! 136: ipstat.ips_odropped++; ! 137: goto sendorfree; ! 138: } ! 139: m->m_data += if_maxlinkhdr; ! 140: mhip = mtod(m, struct ip *); ! 141: *mhip = *ip; ! 142: ! 143: /* No options */ ! 144: /* if (hlen > sizeof (struct ip)) { ! 145: * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); ! 146: * mhip->ip_hl = mhlen >> 2; ! 147: * } ! 148: */ ! 149: m->m_len = mhlen; ! 150: mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); ! 151: if (ip->ip_off & IP_MF) ! 152: mhip->ip_off |= IP_MF; ! 153: if (off + len >= (u_int16_t)ip->ip_len) ! 154: len = (u_int16_t)ip->ip_len - off; ! 155: else ! 156: mhip->ip_off |= IP_MF; ! 157: mhip->ip_len = htons((u_int16_t)(len + mhlen)); ! 158: ! 159: if (m_copy(m, m0, off, len) < 0) { ! 160: error = -1; ! 161: goto sendorfree; ! 162: } ! 163: ! 164: mhip->ip_off = htons((u_int16_t)mhip->ip_off); ! 165: mhip->ip_sum = 0; ! 166: mhip->ip_sum = cksum(m, mhlen); ! 167: *mnext = m; ! 168: mnext = &m->m_nextpkt; ! 169: ipstat.ips_ofragments++; ! 170: } ! 171: /* ! 172: * Update first fragment by trimming what's been copied out ! 173: * and updating header, then send each fragment (in order). ! 174: */ ! 175: m = m0; ! 176: m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len); ! 177: ip->ip_len = htons((u_int16_t)m->m_len); ! 178: ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF)); ! 179: ip->ip_sum = 0; ! 180: ip->ip_sum = cksum(m, hlen); ! 181: sendorfree: ! 182: for (m = m0; m; m = m0) { ! 183: m0 = m->m_nextpkt; ! 184: m->m_nextpkt = 0; ! 185: if (error == 0) ! 186: if_output(so, m); ! 187: else ! 188: m_freem(m); ! 189: } ! 190: ! 191: if (error == 0) ! 192: ipstat.ips_fragmented++; ! 193: } ! 194: ! 195: done: ! 196: return (error); ! 197: ! 198: bad: ! 199: m_freem(m0); ! 200: goto done; ! 201: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.