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