File:  [Qemu by Fabrice Bellard] / qemu / slirp / ip_output.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:49:11 2018 UTC (3 years ago) by root
Branches: qemu, MAIN
CVS tags: qemu0091, HEAD
qemu 0.9.1

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

unix.superglobalmegacorp.com