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