ip_output.c revision 2628
1187770Sluigi/*
2187770Sluigi * Copyright (c) 1982, 1986, 1988, 1990, 1993
3187770Sluigi *	The Regents of the University of California.  All rights reserved.
4187770Sluigi *
5187770Sluigi * Redistribution and use in source and binary forms, with or without
6187770Sluigi * modification, are permitted provided that the following conditions
7187770Sluigi * are met:
8187770Sluigi * 1. Redistributions of source code must retain the above copyright
9187770Sluigi *    notice, this list of conditions and the following disclaimer.
10187770Sluigi * 2. Redistributions in binary form must reproduce the above copyright
11187770Sluigi *    notice, this list of conditions and the following disclaimer in the
12187770Sluigi *    documentation and/or other materials provided with the distribution.
13187770Sluigi * 3. All advertising materials mentioning features or use of this software
14187770Sluigi *    must display the following acknowledgement:
15187770Sluigi *	This product includes software developed by the University of
16187770Sluigi *	California, Berkeley and its contributors.
17187770Sluigi * 4. Neither the name of the University nor the names of its contributors
18187770Sluigi *    may be used to endorse or promote products derived from this software
19187770Sluigi *    without specific prior written permission.
20187770Sluigi *
21187770Sluigi * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22187770Sluigi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23187770Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24187770Sluigi * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25187770Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26187770Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27187770Sluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28187770Sluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29187770Sluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30187770Sluigi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31187770Sluigi * SUCH DAMAGE.
32187770Sluigi *
33187770Sluigi *	@(#)ip_output.c	8.3 (Berkeley) 1/21/94
34187770Sluigi * $Id: ip_output.c,v 1.6 1994/09/06 22:42:24 wollman Exp $
35187770Sluigi */
36187770Sluigi
37187770Sluigi#include <sys/param.h>
38187770Sluigi#include <sys/systm.h>
39187770Sluigi#include <sys/malloc.h>
40187770Sluigi#include <sys/mbuf.h>
41187770Sluigi#include <sys/errno.h>
42187770Sluigi#include <sys/protosw.h>
43187770Sluigi#include <sys/socket.h>
44187770Sluigi#include <sys/socketvar.h>
45247712Smelifaro
46247712Smelifaro#include <net/if.h>
47247712Smelifaro#include <net/route.h>
48247712Smelifaro
49247712Smelifaro#include <netinet/in.h>
50187770Sluigi#include <netinet/in_systm.h>
51187770Sluigi#include <netinet/ip.h>
52187770Sluigi#include <netinet/in_pcb.h>
53187770Sluigi#include <netinet/in_var.h>
54187770Sluigi#include <netinet/ip_var.h>
55187770Sluigi
56187770Sluigi#ifdef vax
57187770Sluigi#include <machine/mtpr.h>
58187770Sluigi#endif
59187770Sluigi
60187770Sluigiu_short ip_id;
61187770Sluigi
62187770Sluigistatic struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
63187770Sluigistatic void ip_mloopback
64187770Sluigi	__P((struct ifnet *, struct mbuf *, struct sockaddr_in *));
65187770Sluigi
66187770Sluigi/*
67187770Sluigi * IP output.  The packet in mbuf chain m contains a skeletal IP
68187770Sluigi * header (with len, off, ttl, proto, tos, src, dst).
69187770Sluigi * The mbuf chain containing the packet will be freed.
70187770Sluigi * The mbuf opt, if present, will not be freed.
71187770Sluigi */
72187770Sluigiint
73187770Sluigiip_output(m0, opt, ro, flags, imo)
74187770Sluigi	struct mbuf *m0;
75187770Sluigi	struct mbuf *opt;
76187770Sluigi	struct route *ro;
77187770Sluigi	int flags;
78187770Sluigi	struct ip_moptions *imo;
79187770Sluigi{
80187770Sluigi	register struct ip *ip, *mhip;
81187770Sluigi	register struct ifnet *ifp;
82187770Sluigi	register struct mbuf *m = m0;
83187770Sluigi	register int hlen = sizeof (struct ip);
84220802Sglebius	int len, off, error = 0;
85187770Sluigi	struct route iproute;
86187770Sluigi	struct sockaddr_in *dst;
87187770Sluigi	struct in_ifaddr *ia;
88187770Sluigi
89187770Sluigi#ifdef	DIAGNOSTIC
90187770Sluigi	if ((m->m_flags & M_PKTHDR) == 0)
91187770Sluigi		panic("ip_output no HDR");
92187770Sluigi#endif
93187770Sluigi	if (opt) {
94187770Sluigi		m = ip_insertoptions(m, opt, &len);
95187770Sluigi		hlen = len;
96187770Sluigi	}
97187770Sluigi	ip = mtod(m, struct ip *);
98220802Sglebius	/*
99220802Sglebius	 * Fill in IP header.
100187770Sluigi	 */
101187770Sluigi	if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
102220802Sglebius		ip->ip_v = IPVERSION;
103220802Sglebius		ip->ip_off &= IP_DF;
104187770Sluigi		ip->ip_id = htons(ip_id++);
105187770Sluigi		ip->ip_hl = hlen >> 2;
106187770Sluigi		ipstat.ips_localout++;
107220802Sglebius	} else {
108220802Sglebius		hlen = ip->ip_hl << 2;
109220802Sglebius	}
110220802Sglebius	/*
111187770Sluigi	 * Route packet.
112187770Sluigi	 */
113220802Sglebius	if (ro == 0) {
114220802Sglebius		ro = &iproute;
115220802Sglebius		bzero((caddr_t)ro, sizeof (*ro));
116187770Sluigi	}
117220802Sglebius	dst = (struct sockaddr_in *)&ro->ro_dst;
118220802Sglebius	/*
119220802Sglebius	 * If there is a cached route,
120220802Sglebius	 * check that it is to the same destination
121220802Sglebius	 * and is still up.  If not, free it and try again.
122220802Sglebius	 */
123220802Sglebius	if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
124220802Sglebius	   dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
125220802Sglebius		RTFREE(ro->ro_rt);
126220802Sglebius		ro->ro_rt = (struct rtentry *)0;
127220802Sglebius	}
128220802Sglebius	if (ro->ro_rt == 0) {
129220802Sglebius		dst->sin_family = AF_INET;
130220802Sglebius		dst->sin_len = sizeof(*dst);
131220802Sglebius		dst->sin_addr = ip->ip_dst;
132220802Sglebius	}
133220802Sglebius	/*
134220802Sglebius	 * If routing to interface only,
135187770Sluigi	 * short circuit routing lookup.
136187770Sluigi	 */
137187770Sluigi#define ifatoia(ifa)	((struct in_ifaddr *)(ifa))
138187770Sluigi#define sintosa(sin)	((struct sockaddr *)(sin))
139247712Smelifaro	if (flags & IP_ROUTETOIF) {
140187770Sluigi		if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
141187770Sluigi		    (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
142187770Sluigi			ipstat.ips_noroute++;
143247712Smelifaro			error = ENETUNREACH;
144247712Smelifaro			goto bad;
145187770Sluigi		}
146187770Sluigi		ifp = ia->ia_ifp;
147220802Sglebius		ip->ip_ttl = 1;
148220802Sglebius	} else {
149220802Sglebius		if (ro->ro_rt == 0)
150220802Sglebius			rtalloc(ro);
151220802Sglebius		if (ro->ro_rt == 0) {
152187770Sluigi			ipstat.ips_noroute++;
153187770Sluigi			error = EHOSTUNREACH;
154187770Sluigi			goto bad;
155187770Sluigi		}
156187770Sluigi		ia = ifatoia(ro->ro_rt->rt_ifa);
157187770Sluigi		ifp = ro->ro_rt->rt_ifp;
158220802Sglebius		ro->ro_rt->rt_use++;
159220802Sglebius		if (ro->ro_rt->rt_flags & RTF_GATEWAY)
160220802Sglebius			dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
161187770Sluigi	}
162187770Sluigi	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
163187770Sluigi		struct in_multi *inm;
164187770Sluigi		extern struct ifnet loif;
165187770Sluigi
166187770Sluigi		m->m_flags |= M_MCAST;
167187770Sluigi		/*
168187770Sluigi		 * IP destination address is multicast.  Make sure "dst"
169187770Sluigi		 * still points to the address in "ro".  (It may have been
170187770Sluigi		 * changed to point to a gateway address, above.)
171187770Sluigi		 */
172187770Sluigi		dst = (struct sockaddr_in *)&ro->ro_dst;
173187770Sluigi		/*
174187770Sluigi		 * See if the caller provided any multicast options
175220802Sglebius		 */
176220802Sglebius		if (imo != NULL) {
177220802Sglebius			ip->ip_ttl = imo->imo_multicast_ttl;
178220802Sglebius			if (imo->imo_multicast_ifp != NULL)
179220802Sglebius				ifp = imo->imo_multicast_ifp;
180220802Sglebius		} else
181187770Sluigi			ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
182187770Sluigi		/*
183187770Sluigi		 * Confirm that the outgoing interface supports multicast.
184187770Sluigi		 */
185187770Sluigi		if ((ifp->if_flags & IFF_MULTICAST) == 0) {
186187770Sluigi			ipstat.ips_noroute++;
187187770Sluigi			error = ENETUNREACH;
188187770Sluigi			goto bad;
189187770Sluigi		}
190187770Sluigi		/*
191220802Sglebius		 * If source address not specified yet, use address
192220802Sglebius		 * of outgoing interface.
193220802Sglebius		 */
194187770Sluigi		if (ip->ip_src.s_addr == INADDR_ANY) {
195187770Sluigi			register struct in_ifaddr *ia;
196187770Sluigi
197187770Sluigi			for (ia = in_ifaddr; ia; ia = ia->ia_next)
198187770Sluigi				if (ia->ia_ifp == ifp) {
199187770Sluigi					ip->ip_src = IA_SIN(ia)->sin_addr;
200187770Sluigi					break;
201187770Sluigi				}
202187770Sluigi		}
203220802Sglebius
204220802Sglebius		IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
205187770Sluigi		if (inm != NULL &&
206187770Sluigi		   (imo == NULL || imo->imo_multicast_loop)) {
207220802Sglebius			/*
208187770Sluigi			 * If we belong to the destination multicast group
209187770Sluigi			 * on the outgoing interface, and the caller did not
210187770Sluigi			 * forbid loopback, loop back a copy.
211187770Sluigi			 */
212187770Sluigi			ip_mloopback(ifp, m, dst);
213187770Sluigi		}
214187770Sluigi#ifdef MROUTING
215187770Sluigi		else {
216187770Sluigi			/*
217187770Sluigi			 * If we are acting as a multicast router, perform
218187770Sluigi			 * multicast forwarding as if the packet had just
219187770Sluigi			 * arrived on the interface to which we are about
220220802Sglebius			 * to send.  The multicast forwarding function
221220802Sglebius			 * recursively calls this function, using the
222220802Sglebius			 * IP_FORWARDING flag to prevent infinite recursion.
223220802Sglebius			 *
224220802Sglebius			 * Multicasts that are looped back by ip_mloopback(),
225220802Sglebius			 * above, will be forwarded by the ip_input() routine,
226187770Sluigi			 * if necessary.
227220802Sglebius			 */
228220802Sglebius			if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
229220802Sglebius				/*
230187770Sluigi				 * Check if rsvp daemon is running. If not, don't
231220802Sglebius				 * set ip_moptions. This ensures that the packet
232220802Sglebius				 * is multicast and not just sent down one link
233220802Sglebius				 * as prescribed by rsvpd.
234187770Sluigi				 */
235220802Sglebius				if (ip_rsvpd == NULL)
236220802Sglebius				  imo = NULL;
237220802Sglebius				if (ip_mforward(ip, ifp, m, imo) != 0) {
238187770Sluigi					m_freem(m);
239220802Sglebius					goto done;
240220802Sglebius				}
241220802Sglebius			}
242187770Sluigi		}
243220802Sglebius#endif
244220802Sglebius		/*
245220802Sglebius		 * Multicasts with a time-to-live of zero may be looped-
246187770Sluigi		 * back, above, but must not be transmitted on a network.
247220802Sglebius		 * Also, multicasts addressed to the loopback interface
248220802Sglebius		 * are not sent -- the above call to ip_mloopback() will
249220802Sglebius		 * loop back a copy if this host actually belongs to the
250187770Sluigi		 * destination group on the loopback interface.
251220802Sglebius		 */
252220802Sglebius		if (ip->ip_ttl == 0 || ifp == &loif) {
253220802Sglebius			m_freem(m);
254187770Sluigi			goto done;
255220802Sglebius		}
256220802Sglebius
257220802Sglebius		goto sendit;
258220802Sglebius	}
259187770Sluigi#ifndef notdef
260187770Sluigi	/*
261220802Sglebius	 * If source address not specified yet, use address
262187770Sluigi	 * of outgoing interface.
263187770Sluigi	 */
264187770Sluigi	if (ip->ip_src.s_addr == INADDR_ANY)
265187770Sluigi		ip->ip_src = IA_SIN(ia)->sin_addr;
266187770Sluigi#endif
267187770Sluigi	/*
268187770Sluigi	 * Verify that we have any chance at all of being able to queue
269187770Sluigi	 *      the packet or packet fragments
270187770Sluigi	 */
271187770Sluigi	if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >=
272187770Sluigi		ifp->if_snd.ifq_maxlen) {
273187770Sluigi			error = ENOBUFS;
274220802Sglebius			goto bad;
275220802Sglebius	}
276187770Sluigi
277187770Sluigi	/*
278220802Sglebius	 * Look for broadcast address and
279220802Sglebius	 * and verify user is allowed to send
280187770Sluigi	 * such a packet.
281187770Sluigi	 */
282220802Sglebius	if (in_broadcast(dst->sin_addr, ifp)) {
283220802Sglebius		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
284187770Sluigi			error = EADDRNOTAVAIL;
285187770Sluigi			goto bad;
286220802Sglebius		}
287220802Sglebius		if ((flags & IP_ALLOWBROADCAST) == 0) {
288187770Sluigi			error = EACCES;
289187770Sluigi			goto bad;
290220802Sglebius		}
291220802Sglebius		/* don't allow broadcast messages to be fragmented */
292187770Sluigi		if ((u_short)ip->ip_len > ifp->if_mtu) {
293187770Sluigi			error = EMSGSIZE;
294220802Sglebius			goto bad;
295220802Sglebius		}
296187770Sluigi		m->m_flags |= M_BCAST;
297187770Sluigi	} else
298220802Sglebius		m->m_flags &= ~M_BCAST;
299220802Sglebius
300187770Sluigisendit:
301187770Sluigi	/*
302220802Sglebius	 * If small enough for interface, can just send directly.
303187770Sluigi	 */
304187770Sluigi	if ((u_short)ip->ip_len <= ifp->if_mtu) {
305187770Sluigi		ip->ip_len = htons((u_short)ip->ip_len);
306187770Sluigi		ip->ip_off = htons((u_short)ip->ip_off);
307187770Sluigi		ip->ip_sum = 0;
308187770Sluigi		ip->ip_sum = in_cksum(m, hlen);
309187770Sluigi		error = (*ifp->if_output)(ifp, m,
310187770Sluigi				(struct sockaddr *)dst, ro->ro_rt);
311187770Sluigi		goto done;
312187770Sluigi	}
313187770Sluigi	/*
314187770Sluigi	 * Too large for interface; fragment if possible.
315187770Sluigi	 * Must be able to put at least 8 bytes per fragment.
316187770Sluigi	 */
317187770Sluigi	if (ip->ip_off & IP_DF) {
318187770Sluigi		error = EMSGSIZE;
319187770Sluigi		ipstat.ips_cantfrag++;
320187770Sluigi		goto bad;
321187770Sluigi	}
322187770Sluigi	len = (ifp->if_mtu - hlen) &~ 7;
323187770Sluigi	if (len < 8) {
324187770Sluigi		error = EMSGSIZE;
325187770Sluigi		goto bad;
326187770Sluigi	}
327187770Sluigi
328220802Sglebius    {
329220802Sglebius	int mhlen, firstlen = len;
330220802Sglebius	struct mbuf **mnext = &m->m_nextpkt;
331187770Sluigi
332187770Sluigi	/*
333187770Sluigi	 * Loop through length of segment after first fragment,
334187770Sluigi	 * make new header and copy data of each part and link onto chain.
335187770Sluigi	 */
336187770Sluigi	m0 = m;
337247712Smelifaro	mhlen = sizeof (struct ip);
338187770Sluigi	for (off = hlen + len; off < (u_short)ip->ip_len; off += len) {
339187770Sluigi		MGETHDR(m, M_DONTWAIT, MT_HEADER);
340187770Sluigi		if (m == 0) {
341187770Sluigi			error = ENOBUFS;
342187770Sluigi			ipstat.ips_odropped++;
343187770Sluigi			goto sendorfree;
344187770Sluigi		}
345187770Sluigi		m->m_data += max_linkhdr;
346240893Smelifaro		mhip = mtod(m, struct ip *);
347187770Sluigi		*mhip = *ip;
348240893Smelifaro		if (hlen > sizeof (struct ip)) {
349240893Smelifaro			mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
350187770Sluigi			mhip->ip_hl = mhlen >> 2;
351187770Sluigi		}
352240893Smelifaro		m->m_len = mhlen;
353240893Smelifaro		mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
354240893Smelifaro		if (ip->ip_off & IP_MF)
355240893Smelifaro			mhip->ip_off |= IP_MF;
356187770Sluigi		if (off + len >= (u_short)ip->ip_len)
357240893Smelifaro			len = (u_short)ip->ip_len - off;
358240893Smelifaro		else
359240893Smelifaro			mhip->ip_off |= IP_MF;
360240893Smelifaro		mhip->ip_len = htons((u_short)(len + mhlen));
361187770Sluigi		m->m_next = m_copy(m0, off, len);
362240892Smelifaro		if (m->m_next == 0) {
363240892Smelifaro			(void) m_free(m);
364240892Smelifaro			error = ENOBUFS;	/* ??? */
365240892Smelifaro			ipstat.ips_odropped++;
366240892Smelifaro			goto sendorfree;
367240892Smelifaro		}
368240892Smelifaro		m->m_pkthdr.len = mhlen + len;
369240892Smelifaro		m->m_pkthdr.rcvif = (struct ifnet *)0;
370240892Smelifaro		mhip->ip_off = htons((u_short)mhip->ip_off);
371240892Smelifaro		mhip->ip_sum = 0;
372240892Smelifaro		mhip->ip_sum = in_cksum(m, mhlen);
373240892Smelifaro		*mnext = m;
374240892Smelifaro		mnext = &m->m_nextpkt;
375240892Smelifaro		ipstat.ips_ofragments++;
376240892Smelifaro	}
377240892Smelifaro	/*
378240893Smelifaro	 * Update first fragment by trimming what's been copied out
379240893Smelifaro	 * and updating header, then send each fragment (in order).
380187770Sluigi	 */
381187770Sluigi	m = m0;
382187770Sluigi	m_adj(m, hlen + firstlen - (u_short)ip->ip_len);
383187770Sluigi	m->m_pkthdr.len = hlen + firstlen;
384187770Sluigi	ip->ip_len = htons((u_short)m->m_pkthdr.len);
385187770Sluigi	ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
386187770Sluigi	ip->ip_sum = 0;
387187770Sluigi	ip->ip_sum = in_cksum(m, hlen);
388187770Sluigisendorfree:
389247712Smelifaro	for (m = m0; m; m = m0) {
390247712Smelifaro		m0 = m->m_nextpkt;
391187770Sluigi		m->m_nextpkt = 0;
392187770Sluigi		if (error == 0)
393187770Sluigi			error = (*ifp->if_output)(ifp, m,
394187770Sluigi			    (struct sockaddr *)dst, ro->ro_rt);
395187770Sluigi		else
396187770Sluigi			m_freem(m);
397187770Sluigi	}
398187770Sluigi
399187770Sluigi	if (error == 0)
400187770Sluigi		ipstat.ips_fragmented++;
401187770Sluigi    }
402187770Sluigidone:
403187770Sluigi	if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt)
404187770Sluigi		RTFREE(ro->ro_rt);
405187770Sluigi	return (error);
406187770Sluigibad:
407187770Sluigi	m_freem(m0);
408187770Sluigi	goto done;
409187770Sluigi}
410187770Sluigi
411187770Sluigi/*
412187770Sluigi * Insert IP options into preformed packet.
413187770Sluigi * Adjust IP destination as required for IP source routing,
414187770Sluigi * as indicated by a non-zero in_addr at the start of the options.
415187770Sluigi */
416187770Sluigistatic struct mbuf *
417187770Sluigiip_insertoptions(m, opt, phlen)
418187770Sluigi	register struct mbuf *m;
419187770Sluigi	struct mbuf *opt;
420187770Sluigi	int *phlen;
421187770Sluigi{
422187770Sluigi	register struct ipoption *p = mtod(opt, struct ipoption *);
423187770Sluigi	struct mbuf *n;
424187770Sluigi	register struct ip *ip = mtod(m, struct ip *);
425187770Sluigi	unsigned optlen;
426187770Sluigi
427187770Sluigi	optlen = opt->m_len - sizeof(p->ipopt_dst);
428187770Sluigi	if (optlen + (u_short)ip->ip_len > IP_MAXPACKET)
429187770Sluigi		return (m);		/* XXX should fail */
430187770Sluigi	if (p->ipopt_dst.s_addr)
431187770Sluigi		ip->ip_dst = p->ipopt_dst;
432187770Sluigi	if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
433187770Sluigi		MGETHDR(n, M_DONTWAIT, MT_HEADER);
434187770Sluigi		if (n == 0)
435187770Sluigi			return (m);
436187770Sluigi		n->m_pkthdr.len = m->m_pkthdr.len + optlen;
437187770Sluigi		m->m_len -= sizeof(struct ip);
438187770Sluigi		m->m_data += sizeof(struct ip);
439187770Sluigi		n->m_next = m;
440187770Sluigi		m = n;
441187770Sluigi		m->m_len = optlen + sizeof(struct ip);
442187770Sluigi		m->m_data += max_linkhdr;
443187770Sluigi		bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
444187770Sluigi	} else {
445187770Sluigi		m->m_data -= optlen;
446187770Sluigi		m->m_len += optlen;
447187770Sluigi		m->m_pkthdr.len += optlen;
448187770Sluigi		ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
449187770Sluigi	}
450187770Sluigi	ip = mtod(m, struct ip *);
451187770Sluigi	bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen);
452187770Sluigi	*phlen = sizeof(struct ip) + optlen;
453187770Sluigi	ip->ip_len += optlen;
454187770Sluigi	return (m);
455187770Sluigi}
456187770Sluigi
457187770Sluigi/*
458187770Sluigi * Copy options from ip to jp,
459187770Sluigi * omitting those not copied during fragmentation.
460187770Sluigi */
461187770Sluigiint
462187770Sluigiip_optcopy(ip, jp)
463187770Sluigi	struct ip *ip, *jp;
464187770Sluigi{
465247712Smelifaro	register u_char *cp, *dp;
466187770Sluigi	int opt, optlen, cnt;
467187770Sluigi
468187770Sluigi	cp = (u_char *)(ip + 1);
469187770Sluigi	dp = (u_char *)(jp + 1);
470187770Sluigi	cnt = (ip->ip_hl << 2) - sizeof (struct ip);
471187770Sluigi	for (; cnt > 0; cnt -= optlen, cp += optlen) {
472187770Sluigi		opt = cp[0];
473247712Smelifaro		if (opt == IPOPT_EOL)
474247712Smelifaro			break;
475187770Sluigi		if (opt == IPOPT_NOP) {
476187770Sluigi			/* Preserve for IP mcast tunnel's LSRR alignment. */
477187770Sluigi			*dp++ = IPOPT_NOP;
478187770Sluigi			optlen = 1;
479187770Sluigi			continue;
480187770Sluigi		} else
481187770Sluigi			optlen = cp[IPOPT_OLEN];
482187770Sluigi		/* bogus lengths should have been caught by ip_dooptions */
483187770Sluigi		if (optlen > cnt)
484187770Sluigi			optlen = cnt;
485187770Sluigi		if (IPOPT_COPIED(opt)) {
486187770Sluigi			bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen);
487187770Sluigi			dp += optlen;
488187770Sluigi		}
489187770Sluigi	}
490187770Sluigi	for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
491187770Sluigi		*dp++ = IPOPT_EOL;
492187770Sluigi	return (optlen);
493187770Sluigi}
494187770Sluigi
495247712Smelifaro/*
496187770Sluigi * IP socket option processing.
497187770Sluigi */
498247712Smelifaroint
499240892Smelifaroip_ctloutput(op, so, level, optname, mp)
500240892Smelifaro	int op;
501240892Smelifaro	struct socket *so;
502240892Smelifaro	int level, optname;
503240892Smelifaro	struct mbuf **mp;
504187770Sluigi{
505187770Sluigi	register struct inpcb *inp = sotoinpcb(so);
506187770Sluigi	register struct mbuf *m = *mp;
507187770Sluigi	register int optval = 0;
508187770Sluigi	int error = 0;
509187770Sluigi
510187770Sluigi	if (level != IPPROTO_IP) {
511187770Sluigi		error = EINVAL;
512187770Sluigi		if (op == PRCO_SETOPT && *mp)
513187770Sluigi			(void) m_free(*mp);
514187770Sluigi	} else switch (op) {
515187770Sluigi
516187770Sluigi	case PRCO_SETOPT:
517247712Smelifaro		switch (optname) {
518187770Sluigi		case IP_OPTIONS:
519187770Sluigi#ifdef notyet
520247712Smelifaro		case IP_RETOPTS:
521240892Smelifaro			return (ip_pcbopts(optname, &inp->inp_options, m));
522240892Smelifaro#else
523240892Smelifaro			return (ip_pcbopts(&inp->inp_options, m));
524240892Smelifaro#endif
525240892Smelifaro
526187770Sluigi		case IP_TOS:
527187770Sluigi		case IP_TTL:
528187770Sluigi		case IP_RECVOPTS:
529187770Sluigi		case IP_RECVRETOPTS:
530187770Sluigi		case IP_RECVDSTADDR:
531187770Sluigi			if (m->m_len != sizeof(int))
532187770Sluigi				error = EINVAL;
533187770Sluigi			else {
534187770Sluigi				optval = *mtod(m, int *);
535187770Sluigi				switch (optname) {
536187770Sluigi
537				case IP_TOS:
538					inp->inp_ip.ip_tos = optval;
539					break;
540
541				case IP_TTL:
542					inp->inp_ip.ip_ttl = optval;
543					break;
544#define	OPTSET(bit) \
545	if (optval) \
546		inp->inp_flags |= bit; \
547	else \
548		inp->inp_flags &= ~bit;
549
550				case IP_RECVOPTS:
551					OPTSET(INP_RECVOPTS);
552					break;
553
554				case IP_RECVRETOPTS:
555					OPTSET(INP_RECVRETOPTS);
556					break;
557
558				case IP_RECVDSTADDR:
559					OPTSET(INP_RECVDSTADDR);
560					break;
561				}
562			}
563			break;
564#undef OPTSET
565
566		case IP_MULTICAST_IF:
567		case IP_MULTICAST_VIF:
568		case IP_MULTICAST_TTL:
569		case IP_MULTICAST_LOOP:
570		case IP_ADD_MEMBERSHIP:
571		case IP_DROP_MEMBERSHIP:
572			error = ip_setmoptions(optname, &inp->inp_moptions, m);
573			break;
574
575		default:
576			error = ENOPROTOOPT;
577			break;
578		}
579		if (m)
580			(void)m_free(m);
581		break;
582
583	case PRCO_GETOPT:
584		switch (optname) {
585		case IP_OPTIONS:
586		case IP_RETOPTS:
587			*mp = m = m_get(M_WAIT, MT_SOOPTS);
588			if (inp->inp_options) {
589				m->m_len = inp->inp_options->m_len;
590				bcopy(mtod(inp->inp_options, caddr_t),
591				    mtod(m, caddr_t), (unsigned)m->m_len);
592			} else
593				m->m_len = 0;
594			break;
595
596		case IP_TOS:
597		case IP_TTL:
598		case IP_RECVOPTS:
599		case IP_RECVRETOPTS:
600		case IP_RECVDSTADDR:
601			*mp = m = m_get(M_WAIT, MT_SOOPTS);
602			m->m_len = sizeof(int);
603			switch (optname) {
604
605			case IP_TOS:
606				optval = inp->inp_ip.ip_tos;
607				break;
608
609			case IP_TTL:
610				optval = inp->inp_ip.ip_ttl;
611				break;
612
613#define	OPTBIT(bit)	(inp->inp_flags & bit ? 1 : 0)
614
615			case IP_RECVOPTS:
616				optval = OPTBIT(INP_RECVOPTS);
617				break;
618
619			case IP_RECVRETOPTS:
620				optval = OPTBIT(INP_RECVRETOPTS);
621				break;
622
623			case IP_RECVDSTADDR:
624				optval = OPTBIT(INP_RECVDSTADDR);
625				break;
626			}
627			*mtod(m, int *) = optval;
628			break;
629
630		case IP_MULTICAST_IF:
631		case IP_MULTICAST_VIF:
632		case IP_MULTICAST_TTL:
633		case IP_MULTICAST_LOOP:
634		case IP_ADD_MEMBERSHIP:
635		case IP_DROP_MEMBERSHIP:
636			error = ip_getmoptions(optname, inp->inp_moptions, mp);
637			break;
638
639		default:
640			error = ENOPROTOOPT;
641			break;
642		}
643		break;
644	}
645	return (error);
646}
647
648/*
649 * Set up IP options in pcb for insertion in output packets.
650 * Store in mbuf with pointer in pcbopt, adding pseudo-option
651 * with destination address if source routed.
652 */
653int
654#ifdef notyet
655ip_pcbopts(optname, pcbopt, m)
656	int optname;
657#else
658ip_pcbopts(pcbopt, m)
659#endif
660	struct mbuf **pcbopt;
661	register struct mbuf *m;
662{
663	register cnt, optlen;
664	register u_char *cp;
665	u_char opt;
666
667	/* turn off any old options */
668	if (*pcbopt)
669		(void)m_free(*pcbopt);
670	*pcbopt = 0;
671	if (m == (struct mbuf *)0 || m->m_len == 0) {
672		/*
673		 * Only turning off any previous options.
674		 */
675		if (m)
676			(void)m_free(m);
677		return (0);
678	}
679
680#ifndef	vax
681	if (m->m_len % sizeof(long))
682		goto bad;
683#endif
684	/*
685	 * IP first-hop destination address will be stored before
686	 * actual options; move other options back
687	 * and clear it when none present.
688	 */
689	if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
690		goto bad;
691	cnt = m->m_len;
692	m->m_len += sizeof(struct in_addr);
693	cp = mtod(m, u_char *) + sizeof(struct in_addr);
694	ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
695	bzero(mtod(m, caddr_t), sizeof(struct in_addr));
696
697	for (; cnt > 0; cnt -= optlen, cp += optlen) {
698		opt = cp[IPOPT_OPTVAL];
699		if (opt == IPOPT_EOL)
700			break;
701		if (opt == IPOPT_NOP)
702			optlen = 1;
703		else {
704			optlen = cp[IPOPT_OLEN];
705			if (optlen <= IPOPT_OLEN || optlen > cnt)
706				goto bad;
707		}
708		switch (opt) {
709
710		default:
711			break;
712
713		case IPOPT_LSRR:
714		case IPOPT_SSRR:
715			/*
716			 * user process specifies route as:
717			 *	->A->B->C->D
718			 * D must be our final destination (but we can't
719			 * check that since we may not have connected yet).
720			 * A is first hop destination, which doesn't appear in
721			 * actual IP option, but is stored before the options.
722			 */
723			if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
724				goto bad;
725			m->m_len -= sizeof(struct in_addr);
726			cnt -= sizeof(struct in_addr);
727			optlen -= sizeof(struct in_addr);
728			cp[IPOPT_OLEN] = optlen;
729			/*
730			 * Move first hop before start of options.
731			 */
732			bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
733			    sizeof(struct in_addr));
734			/*
735			 * Then copy rest of options back
736			 * to close up the deleted entry.
737			 */
738			ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
739			    sizeof(struct in_addr)),
740			    (caddr_t)&cp[IPOPT_OFFSET+1],
741			    (unsigned)cnt + sizeof(struct in_addr));
742			break;
743		}
744	}
745	if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
746		goto bad;
747	*pcbopt = m;
748	return (0);
749
750bad:
751	(void)m_free(m);
752	return (EINVAL);
753}
754
755/*
756 * Set the IP multicast options in response to user setsockopt().
757 */
758int
759ip_setmoptions(optname, imop, m)
760	int optname;
761	struct ip_moptions **imop;
762	struct mbuf *m;
763{
764	register int error = 0;
765	u_char loop;
766	register int i;
767	struct in_addr addr;
768	register struct ip_mreq *mreq;
769	register struct ifnet *ifp;
770	register struct ip_moptions *imo = *imop;
771	struct route ro;
772	register struct sockaddr_in *dst;
773
774	if (imo == NULL) {
775		/*
776		 * No multicast option buffer attached to the pcb;
777		 * allocate one and initialize to default values.
778		 */
779		imo = (struct ip_moptions*)malloc(sizeof(*imo), M_IPMOPTS,
780		    M_WAITOK);
781
782		if (imo == NULL)
783			return (ENOBUFS);
784		*imop = imo;
785		imo->imo_multicast_ifp = NULL;
786		imo->imo_multicast_vif = 0;
787		imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
788		imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
789		imo->imo_num_memberships = 0;
790	}
791
792	switch (optname) {
793#ifdef MROUTING
794	/* store an index number for the vif you wanna use in the send */
795	case IP_MULTICAST_VIF:
796		if (m == NULL || m->m_len != sizeof(int)) {
797			error = EINVAL;
798			break;
799		}
800		i = *(mtod(m, int *));
801		if (!legal_vif_num(i)) {
802			error = EINVAL;
803			break;
804		}
805		imo->imo_multicast_vif = i;
806		break;
807#endif
808
809	case IP_MULTICAST_IF:
810		/*
811		 * Select the interface for outgoing multicast packets.
812		 */
813		if (m == NULL || m->m_len != sizeof(struct in_addr)) {
814			error = EINVAL;
815			break;
816		}
817		addr = *(mtod(m, struct in_addr *));
818		/*
819		 * INADDR_ANY is used to remove a previous selection.
820		 * When no interface is selected, a default one is
821		 * chosen every time a multicast packet is sent.
822		 */
823		if (addr.s_addr == INADDR_ANY) {
824			imo->imo_multicast_ifp = NULL;
825			break;
826		}
827		/*
828		 * The selected interface is identified by its local
829		 * IP address.  Find the interface and confirm that
830		 * it supports multicasting.
831		 */
832		INADDR_TO_IFP(addr, ifp);
833		if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
834			error = EADDRNOTAVAIL;
835			break;
836		}
837		imo->imo_multicast_ifp = ifp;
838		break;
839
840	case IP_MULTICAST_TTL:
841		/*
842		 * Set the IP time-to-live for outgoing multicast packets.
843		 */
844		if (m == NULL || m->m_len != 1) {
845			error = EINVAL;
846			break;
847		}
848		imo->imo_multicast_ttl = *(mtod(m, u_char *));
849		break;
850
851	case IP_MULTICAST_LOOP:
852		/*
853		 * Set the loopback flag for outgoing multicast packets.
854		 * Must be zero or one.
855		 */
856		if (m == NULL || m->m_len != 1 ||
857		   (loop = *(mtod(m, u_char *))) > 1) {
858			error = EINVAL;
859			break;
860		}
861		imo->imo_multicast_loop = loop;
862		break;
863
864	case IP_ADD_MEMBERSHIP:
865		/*
866		 * Add a multicast group membership.
867		 * Group must be a valid IP multicast address.
868		 */
869		if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
870			error = EINVAL;
871			break;
872		}
873		mreq = mtod(m, struct ip_mreq *);
874		if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
875			error = EINVAL;
876			break;
877		}
878		/*
879		 * If no interface address was provided, use the interface of
880		 * the route to the given multicast address.
881		 */
882		if (mreq->imr_interface.s_addr == INADDR_ANY) {
883			ro.ro_rt = NULL;
884			dst = (struct sockaddr_in *)&ro.ro_dst;
885			dst->sin_len = sizeof(*dst);
886			dst->sin_family = AF_INET;
887			dst->sin_addr = mreq->imr_multiaddr;
888			rtalloc(&ro);
889			if (ro.ro_rt == NULL) {
890				error = EADDRNOTAVAIL;
891				break;
892			}
893			ifp = ro.ro_rt->rt_ifp;
894			rtfree(ro.ro_rt);
895		}
896		else {
897			INADDR_TO_IFP(mreq->imr_interface, ifp);
898		}
899		/*
900		 * See if we found an interface, and confirm that it
901		 * supports multicast.
902		 */
903		if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
904			error = EADDRNOTAVAIL;
905			break;
906		}
907		/*
908		 * See if the membership already exists or if all the
909		 * membership slots are full.
910		 */
911		for (i = 0; i < imo->imo_num_memberships; ++i) {
912			if (imo->imo_membership[i]->inm_ifp == ifp &&
913			    imo->imo_membership[i]->inm_addr.s_addr
914						== mreq->imr_multiaddr.s_addr)
915				break;
916		}
917		if (i < imo->imo_num_memberships) {
918			error = EADDRINUSE;
919			break;
920		}
921		if (i == IP_MAX_MEMBERSHIPS) {
922			error = ETOOMANYREFS;
923			break;
924		}
925		/*
926		 * Everything looks good; add a new record to the multicast
927		 * address list for the given interface.
928		 */
929		if ((imo->imo_membership[i] =
930		    in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
931			error = ENOBUFS;
932			break;
933		}
934		++imo->imo_num_memberships;
935		break;
936
937	case IP_DROP_MEMBERSHIP:
938		/*
939		 * Drop a multicast group membership.
940		 * Group must be a valid IP multicast address.
941		 */
942		if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
943			error = EINVAL;
944			break;
945		}
946		mreq = mtod(m, struct ip_mreq *);
947		if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
948			error = EINVAL;
949			break;
950		}
951		/*
952		 * If an interface address was specified, get a pointer
953		 * to its ifnet structure.
954		 */
955		if (mreq->imr_interface.s_addr == INADDR_ANY)
956			ifp = NULL;
957		else {
958			INADDR_TO_IFP(mreq->imr_interface, ifp);
959			if (ifp == NULL) {
960				error = EADDRNOTAVAIL;
961				break;
962			}
963		}
964		/*
965		 * Find the membership in the membership array.
966		 */
967		for (i = 0; i < imo->imo_num_memberships; ++i) {
968			if ((ifp == NULL ||
969			     imo->imo_membership[i]->inm_ifp == ifp) &&
970			     imo->imo_membership[i]->inm_addr.s_addr ==
971			     mreq->imr_multiaddr.s_addr)
972				break;
973		}
974		if (i == imo->imo_num_memberships) {
975			error = EADDRNOTAVAIL;
976			break;
977		}
978		/*
979		 * Give up the multicast address record to which the
980		 * membership points.
981		 */
982		in_delmulti(imo->imo_membership[i]);
983		/*
984		 * Remove the gap in the membership array.
985		 */
986		for (++i; i < imo->imo_num_memberships; ++i)
987			imo->imo_membership[i-1] = imo->imo_membership[i];
988		--imo->imo_num_memberships;
989		break;
990
991	default:
992		error = EOPNOTSUPP;
993		break;
994	}
995
996	/*
997	 * If all options have default values, no need to keep the mbuf.
998	 */
999	if (imo->imo_multicast_ifp == NULL &&
1000	    imo->imo_multicast_vif == 0 &&
1001	    imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
1002	    imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
1003	    imo->imo_num_memberships == 0) {
1004		free(*imop, M_IPMOPTS);
1005		*imop = NULL;
1006	}
1007
1008	return (error);
1009}
1010
1011/*
1012 * Return the IP multicast options in response to user getsockopt().
1013 */
1014int
1015ip_getmoptions(optname, imo, mp)
1016	int optname;
1017	register struct ip_moptions *imo;
1018	register struct mbuf **mp;
1019{
1020	u_char *ttl;
1021	u_char *loop;
1022	struct in_addr *addr;
1023	struct in_ifaddr *ia;
1024
1025	*mp = m_get(M_WAIT, MT_SOOPTS);
1026
1027	switch (optname) {
1028
1029	case IP_MULTICAST_VIF:
1030		if (imo != NULL)
1031			*(mtod(*mp, int *)) = imo->imo_multicast_vif;
1032		else
1033			*(mtod(*mp, int *)) = 7890;
1034		(*mp)->m_len = sizeof(int);
1035		return(0);
1036
1037	case IP_MULTICAST_IF:
1038		addr = mtod(*mp, struct in_addr *);
1039		(*mp)->m_len = sizeof(struct in_addr);
1040		if (imo == NULL || imo->imo_multicast_ifp == NULL)
1041			addr->s_addr = INADDR_ANY;
1042		else {
1043			IFP_TO_IA(imo->imo_multicast_ifp, ia);
1044			addr->s_addr = (ia == NULL) ? INADDR_ANY
1045					: IA_SIN(ia)->sin_addr.s_addr;
1046		}
1047		return (0);
1048
1049	case IP_MULTICAST_TTL:
1050		ttl = mtod(*mp, u_char *);
1051		(*mp)->m_len = 1;
1052		*ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
1053				     : imo->imo_multicast_ttl;
1054		return (0);
1055
1056	case IP_MULTICAST_LOOP:
1057		loop = mtod(*mp, u_char *);
1058		(*mp)->m_len = 1;
1059		*loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
1060				      : imo->imo_multicast_loop;
1061		return (0);
1062
1063	default:
1064		return (EOPNOTSUPP);
1065	}
1066}
1067
1068/*
1069 * Discard the IP multicast options.
1070 */
1071void
1072ip_freemoptions(imo)
1073	register struct ip_moptions *imo;
1074{
1075	register int i;
1076
1077	if (imo != NULL) {
1078		for (i = 0; i < imo->imo_num_memberships; ++i)
1079			in_delmulti(imo->imo_membership[i]);
1080		free(imo, M_IPMOPTS);
1081	}
1082}
1083
1084/*
1085 * Routine called from ip_output() to loop back a copy of an IP multicast
1086 * packet to the input queue of a specified interface.  Note that this
1087 * calls the output routine of the loopback "driver", but with an interface
1088 * pointer that might NOT be &loif -- easier than replicating that code here.
1089 */
1090static void
1091ip_mloopback(ifp, m, dst)
1092	struct ifnet *ifp;
1093	register struct mbuf *m;
1094	register struct sockaddr_in *dst;
1095{
1096	register struct ip *ip;
1097	struct mbuf *copym;
1098
1099	copym = m_copy(m, 0, M_COPYALL);
1100	if (copym != NULL) {
1101		/*
1102		 * We don't bother to fragment if the IP length is greater
1103		 * than the interface's MTU.  Can this possibly matter?
1104		 */
1105		ip = mtod(copym, struct ip *);
1106		ip->ip_len = htons((u_short)ip->ip_len);
1107		ip->ip_off = htons((u_short)ip->ip_off);
1108		ip->ip_sum = 0;
1109		ip->ip_sum = in_cksum(copym, ip->ip_hl << 2);
1110		(void) looutput(ifp, copym, (struct sockaddr *)dst, NULL);
1111	}
1112}
1113