1 /* SPDX-License-Identifier: BSD-3-Clause */
3 * Copyright (c) 1982, 1986, 1988, 1990, 1993
4 * The Regents of the University of California. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
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
35 * Changes and additions relating to SLiRP are
36 * Copyright (c) 1995 Danny Gasparovski.
41 /* Number of packets queued before we start sending
42 * (to prevent allocing too many mbufs) */
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.
52 ip_output(struct socket
*so
, struct mbuf
*m0
)
54 Slirp
*slirp
= m0
->slirp
;
55 register struct ip
*ip
;
56 register struct mbuf
*m
= m0
;
57 register int hlen
= sizeof(struct ip
);
58 int len
, off
, error
= 0;
60 DEBUG_CALL("ip_output");
61 DEBUG_ARG("so = %p", so
);
62 DEBUG_ARG("m0 = %p", m0
);
64 ip
= mtod(m
, struct ip
*);
70 ip
->ip_id
= htons(slirp
->ip_id
++);
71 ip
->ip_hl
= hlen
>> 2;
74 * If small enough for interface, can just send directly.
76 if ((uint16_t)ip
->ip_len
<= IF_MTU
) {
77 ip
->ip_len
= htons((uint16_t)ip
->ip_len
);
78 ip
->ip_off
= htons((uint16_t)ip
->ip_off
);
80 ip
->ip_sum
= cksum(m
, hlen
);
87 * Too large for interface; fragment if possible.
88 * Must be able to put at least 8 bytes per fragment.
90 if (ip
->ip_off
& IP_DF
) {
95 len
= (IF_MTU
- hlen
) &~ 7; /* ip databytes per packet */
102 int mhlen
, firstlen
= len
;
103 struct mbuf
**mnext
= &m
->m_nextpkt
;
106 * Loop through length of segment after first fragment,
107 * make new header and copy data of each part and link onto chain.
110 mhlen
= sizeof (struct ip
);
111 for (off
= hlen
+ len
; off
< (uint16_t)ip
->ip_len
; off
+= len
) {
112 register struct ip
*mhip
;
118 m
->m_data
+= IF_MAXLINKHDR
;
119 mhip
= mtod(m
, struct ip
*);
123 mhip
->ip_off
= ((off
- hlen
) >> 3) + (ip
->ip_off
& ~IP_MF
);
124 if (ip
->ip_off
& IP_MF
)
125 mhip
->ip_off
|= IP_MF
;
126 if (off
+ len
>= (uint16_t)ip
->ip_len
)
127 len
= (uint16_t)ip
->ip_len
- off
;
129 mhip
->ip_off
|= IP_MF
;
130 mhip
->ip_len
= htons((uint16_t)(len
+ mhlen
));
132 if (m_copy(m
, m0
, off
, len
) < 0) {
137 mhip
->ip_off
= htons((uint16_t)mhip
->ip_off
);
139 mhip
->ip_sum
= cksum(m
, mhlen
);
141 mnext
= &m
->m_nextpkt
;
144 * Update first fragment by trimming what's been copied out
145 * and updating header, then send each fragment (in order).
148 m_adj(m
, hlen
+ firstlen
- (uint16_t)ip
->ip_len
);
149 ip
->ip_len
= htons((uint16_t)m
->m_len
);
150 ip
->ip_off
= htons((uint16_t)(ip
->ip_off
| IP_MF
));
152 ip
->ip_sum
= cksum(m
, hlen
);
154 for (m
= m0
; m
; m
= m0
) {