Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/ip_output.c
2 views
/* SPDX-License-Identifier: BSD-3-Clause */1/*2* Copyright (c) 1982, 1986, 1988, 1990, 19933* The Regents of the University of California. All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13* 3. Neither the name of the University nor the names of its contributors14* may be used to endorse or promote products derived from this software15* without specific prior written permission.16*17* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*29* @(#)ip_output.c 8.3 (Berkeley) 1/21/9430* ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp31*/3233/*34* Changes and additions relating to SLiRP are35* Copyright (c) 1995 Danny Gasparovski.36*/3738#include "slirp.h"3940/* Number of packets queued before we start sending41* (to prevent allocing too many mbufs) */42#define IF_THRESH 104344/*45* IP output. The packet in mbuf chain m contains a skeletal IP46* header (with len, off, ttl, proto, tos, src, dst).47* The mbuf chain containing the packet will be freed.48* The mbuf opt, if present, will not be freed.49*/50int ip_output(struct socket *so, struct mbuf *m0)51{52Slirp *slirp = m0->slirp;53M_DUP_DEBUG(slirp, m0, 0, 0);5455register struct ip *ip;56register struct mbuf *m = m0;57register int hlen = sizeof(struct ip);58int len, off, error = 0;5960DEBUG_CALL("ip_output");61DEBUG_ARG("so = %p", so);62DEBUG_ARG("m0 = %p", m0);6364ip = mtod(m, struct ip *);65/*66* Fill in IP header.67*/68ip->ip_v = IPVERSION;69ip->ip_off &= IP_DF;70ip->ip_id = htons(slirp->ip_id++);71ip->ip_hl = hlen >> 2;7273/*74* If small enough for interface, can just send directly.75*/76if ((uint16_t)ip->ip_len <= slirp->if_mtu) {77ip->ip_len = htons((uint16_t)ip->ip_len);78ip->ip_off = htons((uint16_t)ip->ip_off);79ip->ip_sum = 0;80ip->ip_sum = cksum(m, hlen);8182if_output(so, m);83goto done;84}8586/*87* Too large for interface; fragment if possible.88* Must be able to put at least 8 bytes per fragment.89*/90if (ip->ip_off & IP_DF) {91error = -1;92goto bad;93}9495len = (slirp->if_mtu - hlen) & ~7; /* ip databytes per packet */96if (len < 8) {97error = -1;98goto bad;99}100101{102int mhlen, firstlen = len;103struct mbuf **mnext = &m->m_nextpkt;104105/*106* Loop through length of segment after first fragment,107* make new header and copy data of each part and link onto chain.108*/109m0 = m;110mhlen = sizeof(struct ip);111for (off = hlen + len; off < (uint16_t)ip->ip_len; off += len) {112register struct ip *mhip;113m = m_get(slirp);114if (m == NULL) {115error = -1;116goto sendorfree;117}118m->m_data += IF_MAXLINKHDR;119mhip = mtod(m, struct ip *);120*mhip = *ip;121122m->m_len = mhlen;123mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);124if (ip->ip_off & IP_MF)125mhip->ip_off |= IP_MF;126if (off + len >= (uint16_t)ip->ip_len)127len = (uint16_t)ip->ip_len - off;128else129mhip->ip_off |= IP_MF;130mhip->ip_len = htons((uint16_t)(len + mhlen));131132if (m_copy(m, m0, off, len) < 0) {133error = -1;134goto sendorfree;135}136137mhip->ip_off = htons((uint16_t)mhip->ip_off);138mhip->ip_sum = 0;139mhip->ip_sum = cksum(m, mhlen);140*mnext = m;141mnext = &m->m_nextpkt;142}143/*144* Update first fragment by trimming what's been copied out145* and updating header, then send each fragment (in order).146*/147m = m0;148m_adj(m, hlen + firstlen - (uint16_t)ip->ip_len);149ip->ip_len = htons((uint16_t)m->m_len);150ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF));151ip->ip_sum = 0;152ip->ip_sum = cksum(m, hlen);153sendorfree:154for (m = m0; m; m = m0) {155m0 = m->m_nextpkt;156m->m_nextpkt = NULL;157if (error == 0)158if_output(so, m);159else160m_free(m);161}162}163164done:165return (error);166167bad:168m_free(m0);169goto done;170}171172173