Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/ip_output.c
2 views
1
/* SPDX-License-Identifier: BSD-3-Clause */
2
/*
3
* Copyright (c) 1982, 1986, 1988, 1990, 1993
4
* The Regents of the University of California. All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
* 3. Neither the name of the University nor the names of its contributors
15
* may be used to endorse or promote products derived from this software
16
* without specific prior written permission.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*
30
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94
31
* ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp
32
*/
33
34
/*
35
* Changes and additions relating to SLiRP are
36
* Copyright (c) 1995 Danny Gasparovski.
37
*/
38
39
#include "slirp.h"
40
41
/* Number of packets queued before we start sending
42
* (to prevent allocing too many mbufs) */
43
#define IF_THRESH 10
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 ip_output(struct socket *so, struct mbuf *m0)
52
{
53
Slirp *slirp = m0->slirp;
54
M_DUP_DEBUG(slirp, m0, 0, 0);
55
56
register struct ip *ip;
57
register struct mbuf *m = m0;
58
register int hlen = sizeof(struct ip);
59
int len, off, error = 0;
60
61
DEBUG_CALL("ip_output");
62
DEBUG_ARG("so = %p", so);
63
DEBUG_ARG("m0 = %p", m0);
64
65
ip = mtod(m, struct ip *);
66
/*
67
* Fill in IP header.
68
*/
69
ip->ip_v = IPVERSION;
70
ip->ip_off &= IP_DF;
71
ip->ip_id = htons(slirp->ip_id++);
72
ip->ip_hl = hlen >> 2;
73
74
/*
75
* If small enough for interface, can just send directly.
76
*/
77
if ((uint16_t)ip->ip_len <= slirp->if_mtu) {
78
ip->ip_len = htons((uint16_t)ip->ip_len);
79
ip->ip_off = htons((uint16_t)ip->ip_off);
80
ip->ip_sum = 0;
81
ip->ip_sum = cksum(m, hlen);
82
83
if_output(so, m);
84
goto done;
85
}
86
87
/*
88
* Too large for interface; fragment if possible.
89
* Must be able to put at least 8 bytes per fragment.
90
*/
91
if (ip->ip_off & IP_DF) {
92
error = -1;
93
goto bad;
94
}
95
96
len = (slirp->if_mtu - hlen) & ~7; /* ip databytes per packet */
97
if (len < 8) {
98
error = -1;
99
goto bad;
100
}
101
102
{
103
int mhlen, firstlen = len;
104
struct mbuf **mnext = &m->m_nextpkt;
105
106
/*
107
* Loop through length of segment after first fragment,
108
* make new header and copy data of each part and link onto chain.
109
*/
110
m0 = m;
111
mhlen = sizeof(struct ip);
112
for (off = hlen + len; off < (uint16_t)ip->ip_len; off += len) {
113
register struct ip *mhip;
114
m = m_get(slirp);
115
if (m == NULL) {
116
error = -1;
117
goto sendorfree;
118
}
119
m->m_data += IF_MAXLINKHDR;
120
mhip = mtod(m, struct ip *);
121
*mhip = *ip;
122
123
m->m_len = mhlen;
124
mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
125
if (ip->ip_off & IP_MF)
126
mhip->ip_off |= IP_MF;
127
if (off + len >= (uint16_t)ip->ip_len)
128
len = (uint16_t)ip->ip_len - off;
129
else
130
mhip->ip_off |= IP_MF;
131
mhip->ip_len = htons((uint16_t)(len + mhlen));
132
133
if (m_copy(m, m0, off, len) < 0) {
134
error = -1;
135
goto sendorfree;
136
}
137
138
mhip->ip_off = htons((uint16_t)mhip->ip_off);
139
mhip->ip_sum = 0;
140
mhip->ip_sum = cksum(m, mhlen);
141
*mnext = m;
142
mnext = &m->m_nextpkt;
143
}
144
/*
145
* Update first fragment by trimming what's been copied out
146
* and updating header, then send each fragment (in order).
147
*/
148
m = m0;
149
m_adj(m, hlen + firstlen - (uint16_t)ip->ip_len);
150
ip->ip_len = htons((uint16_t)m->m_len);
151
ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF));
152
ip->ip_sum = 0;
153
ip->ip_sum = cksum(m, hlen);
154
sendorfree:
155
for (m = m0; m; m = m0) {
156
m0 = m->m_nextpkt;
157
m->m_nextpkt = NULL;
158
if (error == 0)
159
if_output(so, m);
160
else
161
m_free(m);
162
}
163
}
164
165
done:
166
return (error);
167
168
bad:
169
m_free(m0);
170
goto done;
171
}
172
173