File:  [Qemu by Fabrice Bellard] / qemu / slirp / ip_output.c
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:02:42 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, qemu1001, qemu1000, qemu0151, HEAD
qemu 0.15.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. 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: /* Number of packets queued before we start sending
   44:  * (to prevent allocing too many mbufs) */
   45: #define IF_THRESH 10
   46: 
   47: /*
   48:  * IP output.  The packet in mbuf chain m contains a skeletal IP
   49:  * header (with len, off, ttl, proto, tos, src, dst).
   50:  * The mbuf chain containing the packet will be freed.
   51:  * The mbuf opt, if present, will not be freed.
   52:  */
   53: int
   54: ip_output(struct socket *so, struct mbuf *m0)
   55: {
   56: 	Slirp *slirp = m0->slirp;
   57: 	register struct ip *ip;
   58: 	register struct mbuf *m = m0;
   59: 	register int hlen = sizeof(struct ip );
   60: 	int len, off, error = 0;
   61: 
   62: 	DEBUG_CALL("ip_output");
   63: 	DEBUG_ARG("so = %lx", (long)so);
   64: 	DEBUG_ARG("m0 = %lx", (long)m0);
   65: 
   66: 	ip = mtod(m, struct ip *);
   67: 	/*
   68: 	 * Fill in IP header.
   69: 	 */
   70: 	ip->ip_v = IPVERSION;
   71: 	ip->ip_off &= IP_DF;
   72: 	ip->ip_id = htons(slirp->ip_id++);
   73: 	ip->ip_hl = hlen >> 2;
   74: 
   75: 	/*
   76: 	 * If small enough for interface, can just send directly.
   77: 	 */
   78: 	if ((uint16_t)ip->ip_len <= IF_MTU) {
   79: 		ip->ip_len = htons((uint16_t)ip->ip_len);
   80: 		ip->ip_off = htons((uint16_t)ip->ip_off);
   81: 		ip->ip_sum = 0;
   82: 		ip->ip_sum = cksum(m, hlen);
   83: 
   84: 		if_output(so, m);
   85: 		goto done;
   86: 	}
   87: 
   88: 	/*
   89: 	 * Too large for interface; fragment if possible.
   90: 	 * Must be able to put at least 8 bytes per fragment.
   91: 	 */
   92: 	if (ip->ip_off & IP_DF) {
   93: 		error = -1;
   94: 		goto bad;
   95: 	}
   96: 
   97: 	len = (IF_MTU - hlen) &~ 7;       /* ip databytes per packet */
   98: 	if (len < 8) {
   99: 		error = -1;
  100: 		goto bad;
  101: 	}
  102: 
  103:     {
  104: 	int mhlen, firstlen = len;
  105: 	struct mbuf **mnext = &m->m_nextpkt;
  106: 
  107: 	/*
  108: 	 * Loop through length of segment after first fragment,
  109: 	 * make new header and copy data of each part and link onto chain.
  110: 	 */
  111: 	m0 = m;
  112: 	mhlen = sizeof (struct ip);
  113: 	for (off = hlen + len; off < (uint16_t)ip->ip_len; off += len) {
  114: 	  register struct ip *mhip;
  115: 	  m = m_get(slirp);
  116:           if (m == NULL) {
  117: 	    error = -1;
  118: 	    goto sendorfree;
  119: 	  }
  120: 	  m->m_data += IF_MAXLINKHDR;
  121: 	  mhip = mtod(m, struct ip *);
  122: 	  *mhip = *ip;
  123: 
  124: 	  m->m_len = mhlen;
  125: 	  mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
  126: 	  if (ip->ip_off & IP_MF)
  127: 	    mhip->ip_off |= IP_MF;
  128: 	  if (off + len >= (uint16_t)ip->ip_len)
  129: 	    len = (uint16_t)ip->ip_len - off;
  130: 	  else
  131: 	    mhip->ip_off |= IP_MF;
  132: 	  mhip->ip_len = htons((uint16_t)(len + mhlen));
  133: 
  134: 	  if (m_copy(m, m0, off, len) < 0) {
  135: 	    error = -1;
  136: 	    goto sendorfree;
  137: 	  }
  138: 
  139: 	  mhip->ip_off = htons((uint16_t)mhip->ip_off);
  140: 	  mhip->ip_sum = 0;
  141: 	  mhip->ip_sum = cksum(m, mhlen);
  142: 	  *mnext = m;
  143: 	  mnext = &m->m_nextpkt;
  144: 	}
  145: 	/*
  146: 	 * Update first fragment by trimming what's been copied out
  147: 	 * and updating header, then send each fragment (in order).
  148: 	 */
  149: 	m = m0;
  150: 	m_adj(m, hlen + firstlen - (uint16_t)ip->ip_len);
  151: 	ip->ip_len = htons((uint16_t)m->m_len);
  152: 	ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF));
  153: 	ip->ip_sum = 0;
  154: 	ip->ip_sum = cksum(m, hlen);
  155: sendorfree:
  156: 	for (m = m0; m; m = m0) {
  157: 		m0 = m->m_nextpkt;
  158:                 m->m_nextpkt = NULL;
  159: 		if (error == 0)
  160: 			if_output(so, m);
  161: 		else
  162: 			m_free(m);
  163: 	}
  164:     }
  165: 
  166: done:
  167: 	return (error);
  168: 
  169: bad:
  170: 	m_free(m0);
  171: 	goto done;
  172: }

unix.superglobalmegacorp.com