2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1982, 1986, 1988, 1990, 1993
30 * The Regents of the University of California. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
61 * $FreeBSD: src/sys/netinet/ip_output.c,v 1.99.2.16 2001/07/19 06:37:26 kris Exp $
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/kernel.h>
69 #include <sys/malloc.h>
71 #include <sys/protosw.h>
72 #include <sys/socket.h>
73 #include <sys/socketvar.h>
74 #include <kern/locks.h>
75 #include <sys/sysctl.h>
78 #include <net/route.h>
80 #include <netinet/in.h>
81 #include <netinet/in_systm.h>
82 #include <netinet/ip.h>
83 #include <netinet/in_pcb.h>
84 #include <netinet/in_var.h>
85 #include <netinet/ip_var.h>
87 #include <netinet/kpi_ipfilter_var.h>
92 #include <sys/kdebug.h>
94 #define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIP, 1)
95 #define DBG_LAYER_END NETDBG_CODE(DBG_NETIP, 3)
96 #define DBG_FNC_IP_OUTPUT NETDBG_CODE(DBG_NETIP, (1 << 8) | 1)
97 #define DBG_FNC_IPSEC4_OUTPUT NETDBG_CODE(DBG_NETIP, (2 << 8) | 1)
99 #define SWAP16(v) ((((v) & 0xff) << 8) | ((v) >> 8))
102 #include <netinet6/ipsec.h>
103 #include <netkey/key.h>
105 #include <netkey/key_debug.h>
107 #define KEYDEBUG(lev,arg)
111 #include <netinet/ip_fw.h>
112 #include <netinet/ip_divert.h>
115 #include <netinet/ip_dummynet.h>
118 #if IPFIREWALL_FORWARD_DEBUG
119 #define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
120 (ntohl(a.s_addr)>>16)&0xFF,\
121 (ntohl(a.s_addr)>>8)&0xFF,\
122 (ntohl(a.s_addr))&0xFF);
126 extern lck_mtx_t
*sadb_mutex
;
131 static struct mbuf
*ip_insertoptions(struct mbuf
*, struct mbuf
*, int *);
132 static struct ifnet
*ip_multicast_if(struct in_addr
*, int *);
133 static void ip_mloopback(struct ifnet
*, struct mbuf
*,
134 struct sockaddr_in
*, int);
135 static int ip_getmoptions(struct sockopt
*, struct ip_moptions
*);
136 static int ip_pcbopts(int, struct mbuf
**, struct mbuf
*);
137 static int ip_setmoptions(struct sockopt
*, struct ip_moptions
**);
139 int ip_createmoptions(struct ip_moptions
**imop
);
140 int ip_addmembership(struct ip_moptions
*imo
, struct ip_mreq
*mreq
);
141 int ip_dropmembership(struct ip_moptions
*imo
, struct ip_mreq
*mreq
);
142 int ip_optcopy(struct ip
*, struct ip
*);
143 extern int (*fr_checkp
)(struct ip
*, int, struct ifnet
*, int, struct mbuf
**);
145 extern struct mbuf
* m_dup(register struct mbuf
*m
, int how
);
148 extern int apple_hwcksum_tx
;
149 extern u_long route_generation
;
151 extern struct protosw inetsw
[];
153 extern struct ip_linklocal_stat ip_linklocal_stat
;
154 extern lck_mtx_t
*ip_mutex
;
156 /* temporary: for testing */
158 extern int ipsec_bypass
;
161 static int ip_maxchainsent
= 0;
162 SYSCTL_INT(_net_inet_ip
, OID_AUTO
, maxchainsent
, CTLFLAG_RW
,
163 &ip_maxchainsent
, 0, "use dlil_output_list");
165 * IP output. The packet in mbuf chain m contains a skeletal IP
166 * header (with len, off, ttl, proto, tos, src, dst).
167 * The mbuf chain containing the packet will be freed.
168 * The mbuf opt, if present, will not be freed.
176 struct ip_moptions
*imo
)
179 error
= ip_output_list(m0
, 0, opt
, ro
, flags
, imo
);
190 struct ip_moptions
*imo
)
192 struct ip
*ip
, *mhip
;
193 struct ifnet
*ifp
= NULL
;
195 int hlen
= sizeof (struct ip
);
196 int len
, off
, error
= 0;
197 struct sockaddr_in
*dst
= NULL
;
198 struct in_ifaddr
*ia
= NULL
;
199 int isbroadcast
, sw_csum
;
200 struct in_addr pkt_dst
;
202 struct route iproute
;
203 struct socket
*so
= NULL
;
204 struct secpolicy
*sp
= NULL
;
206 #if IPFIREWALL_FORWARD
207 int fwd_rewrite_src
= 0;
209 struct ip_fw_args args
;
211 ipfilter_t inject_filter_ref
= 0;
213 struct route dn_route
;
214 struct mbuf
* packetlist
;
217 lck_mtx_lock(ip_mutex
);
219 KERNEL_DEBUG(DBG_FNC_IP_OUTPUT
| DBG_FUNC_START
, 0,0,0,0,0);
224 args
.next_hop
= NULL
;
225 args
.divert_rule
= 0; /* divert cookie */
227 /* Grab info from mtags prepended to the chain */
229 if ((tag
= m_tag_locate(m0
, KERNEL_MODULE_TAG_ID
, KERNEL_TAG_TYPE_DUMMYNET
, NULL
)) != NULL
) {
230 struct dn_pkt_tag
*dn_tag
;
232 dn_tag
= (struct dn_pkt_tag
*)(tag
+1);
233 args
.rule
= dn_tag
->rule
;
235 dn_route
= dn_tag
->ro
;
239 dst
= dn_tag
->dn_dst
;
241 flags
= dn_tag
->flags
;
243 m_tag_delete(m0
, tag
);
245 #endif /* DUMMYNET */
247 if ((tag
= m_tag_locate(m0
, KERNEL_MODULE_TAG_ID
, KERNEL_TAG_TYPE_DIVERT
, NULL
)) != NULL
) {
248 struct divert_tag
*div_tag
;
250 div_tag
= (struct divert_tag
*)(tag
+1);
251 args
.divert_rule
= div_tag
->cookie
;
253 m_tag_delete(m0
, tag
);
255 if ((tag
= m_tag_locate(m0
, KERNEL_MODULE_TAG_ID
, KERNEL_TAG_TYPE_IPFORWARD
, NULL
)) != NULL
) {
256 struct ip_fwd_tag
*ipfwd_tag
;
258 ipfwd_tag
= (struct ip_fwd_tag
*)(tag
+1);
259 args
.next_hop
= ipfwd_tag
->next_hop
;
261 m_tag_delete(m0
, tag
);
267 if ( !m
|| (m
->m_flags
& M_PKTHDR
) != 0)
268 panic("ip_output no HDR");
270 panic("ip_output no route, proto = %d",
271 mtod(m
, struct ip
*)->ip_p
);
274 if (args
.rule
!= NULL
) { /* dummynet already saw us */
275 ip
= mtod(m
, struct ip
*);
276 hlen
= IP_VHL_HL(ip
->ip_vhl
) << 2 ;
277 if (ro
->ro_rt
!= NULL
)
278 ia
= (struct in_ifaddr
*)ro
->ro_rt
->rt_ifa
;
282 if (ipsec_bypass
== 0 && (flags
& IP_NOIPSEC
) == 0) {
283 so
= ipsec_getsocket(m
);
284 (void)ipsec_setsocket(m
, NULL
);
291 if (ipsec_bypass
== 0 && (flags
& IP_NOIPSEC
) == 0) {
292 so
= ipsec_getsocket(m
);
293 (void)ipsec_setsocket(m
, NULL
);
298 * No need to proccess packet twice if we've
301 inject_filter_ref
= ipf_get_inject_filter(m
);
304 m
= ip_insertoptions(m
, opt
, &len
);
307 ip
= mtod(m
, struct ip
*);
308 pkt_dst
= args
.next_hop
? args
.next_hop
->sin_addr
: ip
->ip_dst
;
313 if ((flags
& (IP_FORWARDING
|IP_RAWOUTPUT
)) == 0) {
314 ip
->ip_vhl
= IP_MAKE_VHL(IPVERSION
, hlen
>> 2);
317 ip
->ip_id
= ip_randomid();
319 ip
->ip_id
= htons(ip_id
++);
321 ipstat
.ips_localout
++;
323 hlen
= IP_VHL_HL(ip
->ip_vhl
) << 2;
326 KERNEL_DEBUG(DBG_LAYER_BEG
, ip
->ip_dst
.s_addr
,
327 ip
->ip_src
.s_addr
, ip
->ip_p
, ip
->ip_off
, ip
->ip_len
);
329 dst
= (struct sockaddr_in
*)&ro
->ro_dst
;
332 * If there is a cached route,
333 * check that it is to the same destination
334 * and is still up. If not, free it and try again.
335 * The address family should also be checked in case of sharing the
340 if (ro
->ro_rt
&& (ro
->ro_rt
->generation_id
!= route_generation
) &&
341 ((flags
& (IP_ROUTETOIF
| IP_FORWARDING
)) == 0) && (ip
->ip_src
.s_addr
!= INADDR_ANY
) &&
342 (ifa_foraddr(ip
->ip_src
.s_addr
) == 0)) {
343 error
= EADDRNOTAVAIL
;
347 if (ro
->ro_rt
&& ((ro
->ro_rt
->rt_flags
& RTF_UP
) == 0 ||
348 dst
->sin_family
!= AF_INET
||
349 dst
->sin_addr
.s_addr
!= pkt_dst
.s_addr
)) {
351 ro
->ro_rt
= (struct rtentry
*)0;
353 if (ro
->ro_rt
== 0) {
354 bzero(dst
, sizeof(*dst
));
355 dst
->sin_family
= AF_INET
;
356 dst
->sin_len
= sizeof(*dst
);
357 dst
->sin_addr
= pkt_dst
;
360 * If routing to interface only,
361 * short circuit routing lookup.
363 #define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
364 #define sintosa(sin) ((struct sockaddr *)(sin))
365 if (flags
& IP_ROUTETOIF
) {
367 ifafree(&ia
->ia_ifa
);
368 if ((ia
= ifatoia(ifa_ifwithdstaddr(sintosa(dst
)))) == 0) {
369 if ((ia
= ifatoia(ifa_ifwithnet(sintosa(dst
)))) == 0) {
370 ipstat
.ips_noroute
++;
377 isbroadcast
= in_broadcast(dst
->sin_addr
, ifp
);
380 * If this is the case, we probably don't want to allocate
381 * a protocol-cloned route since we didn't get one from the
382 * ULP. This lets TCP do its thing, while not burdening
383 * forwarding or ICMP with the overhead of cloning a route.
384 * Of course, we still want to do any cloning requested by
385 * the link layer, as this is probably required in all cases
386 * for correct operation (as it is for ARP).
389 rtalloc_ign(ro
, RTF_PRCLONING
);
390 if (ro
->ro_rt
== 0) {
391 ipstat
.ips_noroute
++;
392 error
= EHOSTUNREACH
;
396 ifafree(&ia
->ia_ifa
);
397 ia
= ifatoia(ro
->ro_rt
->rt_ifa
);
400 ifp
= ro
->ro_rt
->rt_ifp
;
402 if (ro
->ro_rt
->rt_flags
& RTF_GATEWAY
)
403 dst
= (struct sockaddr_in
*)ro
->ro_rt
->rt_gateway
;
404 if (ro
->ro_rt
->rt_flags
& RTF_HOST
)
405 isbroadcast
= (ro
->ro_rt
->rt_flags
& RTF_BROADCAST
);
407 isbroadcast
= in_broadcast(dst
->sin_addr
, ifp
);
409 if (IN_MULTICAST(ntohl(pkt_dst
.s_addr
))) {
410 struct in_multi
*inm
;
412 m
->m_flags
|= M_MCAST
;
414 * IP destination address is multicast. Make sure "dst"
415 * still points to the address in "ro". (It may have been
416 * changed to point to a gateway address, above.)
418 dst
= (struct sockaddr_in
*)&ro
->ro_dst
;
420 * See if the caller provided any multicast options
423 if ((flags
& IP_RAWOUTPUT
) == 0) ip
->ip_ttl
= imo
->imo_multicast_ttl
;
424 if (imo
->imo_multicast_ifp
!= NULL
) {
425 ifp
= imo
->imo_multicast_ifp
;
427 if (imo
->imo_multicast_vif
!= -1 &&
428 ((flags
& IP_RAWOUTPUT
) == 0 || ip
->ip_src
.s_addr
== INADDR_ANY
))
430 ip_mcast_src(imo
->imo_multicast_vif
);
432 if ((flags
& IP_RAWOUTPUT
) == 0) ip
->ip_ttl
= IP_DEFAULT_MULTICAST_TTL
;
434 * Confirm that the outgoing interface supports multicast.
436 if ((imo
== NULL
) || (imo
->imo_multicast_vif
== -1)) {
437 if ((ifp
->if_flags
& IFF_MULTICAST
) == 0) {
438 ipstat
.ips_noroute
++;
444 * If source address not specified yet, use address
445 * of outgoing interface.
447 if (ip
->ip_src
.s_addr
== INADDR_ANY
) {
448 register struct in_ifaddr
*ia1
;
450 TAILQ_FOREACH(ia1
, &in_ifaddrhead
, ia_link
)
451 if (ia1
->ia_ifp
== ifp
) {
452 ip
->ip_src
= IA_SIN(ia1
)->sin_addr
;
456 if (ip
->ip_src
.s_addr
== INADDR_ANY
) {
462 ifnet_lock_shared(ifp
);
463 IN_LOOKUP_MULTI(pkt_dst
, ifp
, inm
);
464 ifnet_lock_done(ifp
);
466 (imo
== NULL
|| imo
->imo_multicast_loop
)) {
468 * If we belong to the destination multicast group
469 * on the outgoing interface, and the caller did not
470 * forbid loopback, loop back a copy.
472 if (!TAILQ_EMPTY(&ipv4_filters
)) {
473 struct ipfilter
*filter
;
474 int seen
= (inject_filter_ref
== 0);
475 struct ipf_pktopts
*ippo
= 0, ipf_pktopts
;
479 ipf_pktopts
.ippo_mcast_ifnet
= imo
->imo_multicast_ifp
;
480 ipf_pktopts
.ippo_mcast_ttl
= imo
->imo_multicast_ttl
;
481 ipf_pktopts
.ippo_mcast_loop
= imo
->imo_multicast_loop
;
484 lck_mtx_unlock(ip_mutex
);
487 /* 4135317 - always pass network byte order to filter */
491 TAILQ_FOREACH(filter
, &ipv4_filters
, ipf_link
) {
493 if ((struct ipfilter
*)inject_filter_ref
== filter
)
495 } else if (filter
->ipf_filter
.ipf_output
) {
497 result
= filter
->ipf_filter
.ipf_output(filter
->ipf_filter
.cookie
, (mbuf_t
*)&m
, ippo
);
498 if (result
== EJUSTRETURN
) {
504 lck_mtx_lock(ip_mutex
);
510 /* set back to host byte order */
514 lck_mtx_lock(ip_mutex
);
518 ip_mloopback(ifp
, m
, dst
, hlen
);
522 * If we are acting as a multicast router, perform
523 * multicast forwarding as if the packet had just
524 * arrived on the interface to which we are about
525 * to send. The multicast forwarding function
526 * recursively calls this function, using the
527 * IP_FORWARDING flag to prevent infinite recursion.
529 * Multicasts that are looped back by ip_mloopback(),
530 * above, will be forwarded by the ip_input() routine,
533 if (ip_mrouter
&& (flags
& IP_FORWARDING
) == 0) {
535 * Check if rsvp daemon is running. If not, don't
536 * set ip_moptions. This ensures that the packet
537 * is multicast and not just sent down one link
538 * as prescribed by rsvpd.
542 if (ip_mforward(ip
, ifp
, m
, imo
) != 0) {
544 lck_mtx_unlock(ip_mutex
);
551 * Multicasts with a time-to-live of zero may be looped-
552 * back, above, but must not be transmitted on a network.
553 * Also, multicasts addressed to the loopback interface
554 * are not sent -- the above call to ip_mloopback() will
555 * loop back a copy if this host actually belongs to the
556 * destination group on the loopback interface.
558 if (ip
->ip_ttl
== 0 || ifp
->if_flags
& IFF_LOOPBACK
) {
560 lck_mtx_unlock(ip_mutex
);
568 * If source address not specified yet, use address
569 * of outgoing interface.
571 if (ip
->ip_src
.s_addr
== INADDR_ANY
) {
572 ip
->ip_src
= IA_SIN(ia
)->sin_addr
;
573 #if IPFIREWALL_FORWARD
574 /* Keep note that we did this - if the firewall changes
575 * the next-hop, our interface may change, changing the
576 * default source IP. It's a shame so much effort happens
580 #endif /* IPFIREWALL_FORWARD */
585 * Look for broadcast address and
586 * and verify user is allowed to send
590 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0) {
591 error
= EADDRNOTAVAIL
;
594 if ((flags
& IP_ALLOWBROADCAST
) == 0) {
598 /* don't allow broadcast messages to be fragmented */
599 if ((u_short
)ip
->ip_len
> ifp
->if_mtu
) {
603 m
->m_flags
|= M_BCAST
;
605 m
->m_flags
&= ~M_BCAST
;
610 * Force IP TTL to 255 following draft-ietf-zeroconf-ipv4-linklocal.txt
612 if (IN_LINKLOCAL(ntohl(ip
->ip_src
.s_addr
)) || IN_LINKLOCAL(ntohl(ip
->ip_dst
.s_addr
))) {
613 ip_linklocal_stat
.iplls_out_total
++;
614 if (ip
->ip_ttl
!= MAXTTL
) {
615 ip_linklocal_stat
.iplls_out_badttl
++;
621 if (!didfilter
&& !TAILQ_EMPTY(&ipv4_filters
)) {
622 struct ipfilter
*filter
;
623 int seen
= (inject_filter_ref
== 0);
625 lck_mtx_unlock(ip_mutex
);
628 /* 4135317 - always pass network byte order to filter */
632 TAILQ_FOREACH(filter
, &ipv4_filters
, ipf_link
) {
634 if ((struct ipfilter
*)inject_filter_ref
== filter
)
636 } else if (filter
->ipf_filter
.ipf_output
) {
638 result
= filter
->ipf_filter
.ipf_output(filter
->ipf_filter
.cookie
, (mbuf_t
*)&m
, 0);
639 if (result
== EJUSTRETURN
) {
645 lck_mtx_lock(ip_mutex
);
651 /* set back to host byte order */
656 lck_mtx_lock(ip_mutex
);
660 /* temporary for testing only: bypass ipsec alltogether */
662 if (ipsec_bypass
!= 0 || (flags
& IP_NOIPSEC
) != 0)
665 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_START
, 0,0,0,0,0);
667 lck_mtx_lock(sadb_mutex
);
669 /* get SP for this packet */
671 sp
= ipsec4_getpolicybyaddr(m
, IPSEC_DIR_OUTBOUND
, flags
, &error
);
673 sp
= ipsec4_getpolicybysock(m
, IPSEC_DIR_OUTBOUND
, so
, &error
);
676 ipsecstat
.out_inval
++;
677 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_END
, 0,0,0,0,0);
678 lck_mtx_unlock(sadb_mutex
);
685 switch (sp
->policy
) {
686 case IPSEC_POLICY_DISCARD
:
688 * This packet is just discarded.
690 ipsecstat
.out_polvio
++;
691 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_END
, 1,0,0,0,0);
692 lck_mtx_unlock(sadb_mutex
);
695 case IPSEC_POLICY_BYPASS
:
696 case IPSEC_POLICY_NONE
:
697 /* no need to do IPsec. */
698 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_END
, 2,0,0,0,0);
699 lck_mtx_unlock(sadb_mutex
);
702 case IPSEC_POLICY_IPSEC
:
703 if (sp
->req
== NULL
) {
704 /* acquire a policy */
705 error
= key_spdacquire(sp
);
706 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_END
, 3,0,0,0,0);
707 lck_mtx_unlock(sadb_mutex
);
712 case IPSEC_POLICY_ENTRUST
:
714 printf("ip_output: Invalid policy found. %d\n", sp
->policy
);
717 struct ipsec_output_state state
;
718 bzero(&state
, sizeof(state
));
720 if (flags
& IP_ROUTETOIF
) {
722 bzero(&iproute
, sizeof(iproute
));
725 state
.dst
= (struct sockaddr
*)dst
;
731 * delayed checksums are not currently compatible with IPsec
733 if (m
->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA
) {
735 m
->m_pkthdr
.csum_flags
&= ~CSUM_DELAY_DATA
;
741 lck_mtx_unlock(ip_mutex
);
742 error
= ipsec4_output(&state
, sp
, flags
);
743 lck_mtx_unlock(sadb_mutex
);
744 lck_mtx_lock(ip_mutex
);
748 if (flags
& IP_ROUTETOIF
) {
750 * if we have tunnel mode SA, we may need to ignore
753 if (state
.ro
!= &iproute
|| state
.ro
->ro_rt
!= NULL
) {
754 flags
&= ~IP_ROUTETOIF
;
760 dst
= (struct sockaddr_in
*)state
.dst
;
762 /* mbuf is already reclaimed in ipsec4_output. */
772 printf("ip4_output (ipsec): error code %d\n", error
);
775 /* don't show these error codes to the user */
779 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_END
, 4,0,0,0,0);
784 /* be sure to update variables that are affected by ipsec4_output() */
785 ip
= mtod(m
, struct ip
*);
788 hlen
= IP_VHL_HL(ip
->ip_vhl
) << 2;
790 hlen
= ip
->ip_hl
<< 2;
792 /* Check that there wasn't a route change and src is still valid */
794 if (ro
->ro_rt
&& ro
->ro_rt
->generation_id
!= route_generation
) {
795 if (ifa_foraddr(ip
->ip_src
.s_addr
) == 0 && ((flags
& (IP_ROUTETOIF
| IP_FORWARDING
)) == 0)) {
796 error
= EADDRNOTAVAIL
;
797 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_END
, 5,0,0,0,0);
804 if (ro
->ro_rt
== NULL
) {
805 if ((flags
& IP_ROUTETOIF
) == 0) {
807 "can't update route after IPsec processing\n");
808 error
= EHOSTUNREACH
; /*XXX*/
809 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_END
, 6,0,0,0,0);
814 ifafree(&ia
->ia_ifa
);
815 ia
= ifatoia(ro
->ro_rt
->rt_ifa
);
818 ifp
= ro
->ro_rt
->rt_ifp
;
821 /* make it flipped, again. */
824 KERNEL_DEBUG(DBG_FNC_IPSEC4_OUTPUT
| DBG_FUNC_END
, 7,0xff,0xff,0xff,0xff);
826 /* Pass to filters again */
827 if (!TAILQ_EMPTY(&ipv4_filters
)) {
828 struct ipfilter
*filter
;
830 lck_mtx_unlock(ip_mutex
);
833 /* 4135317 - always pass network byte order to filter */
837 TAILQ_FOREACH(filter
, &ipv4_filters
, ipf_link
) {
838 if (filter
->ipf_filter
.ipf_output
) {
840 result
= filter
->ipf_filter
.ipf_output(filter
->ipf_filter
.cookie
, (mbuf_t
*)&m
, 0);
841 if (result
== EJUSTRETURN
) {
847 lck_mtx_lock(ip_mutex
);
853 /* set back to host byte order */
858 lck_mtx_lock(ip_mutex
);
865 * - Xlate: translate packet's addr/port (NAT).
866 * - Firewall: deny/allow/etc.
867 * - Wrap: fake packet's addr/port <unimpl.>
868 * - Encapsulate: put it in another IP and send out. <unimp.>
873 if ((error
= (*fr_checkp
)(ip
, hlen
, ifp
, 1, &m1
)) || !m1
) {
874 lck_mtx_unlock(ip_mutex
);
877 ip
= mtod(m0
= m
= m1
, struct ip
*);
881 * Check with the firewall...
882 * but not if we are already being fwd'd from a firewall.
884 if (fw_enable
&& IPFW_LOADED
&& !args
.next_hop
) {
885 struct sockaddr_in
*old
= dst
;
890 lck_mtx_unlock(ip_mutex
);
891 off
= ip_fw_chk_ptr(&args
);
896 * On return we must do the following:
897 * IP_FW_PORT_DENY_FLAG -> drop the pkt (XXX new)
898 * 1<=off<= 0xffff -> DIVERT
899 * (off & IP_FW_PORT_DYNT_FLAG) -> send to a DUMMYNET pipe
900 * (off & IP_FW_PORT_TEE_FLAG) -> TEE the packet
901 * dst != old -> IPFIREWALL_FORWARD
902 * off==0, dst==old -> accept
903 * If some of the above modules is not compiled in, then
904 * we should't have to check the corresponding condition
905 * (because the ipfw control socket should not accept
906 * unsupported rules), but better play safe and drop
907 * packets in case of doubt.
910 if ( (off
& IP_FW_PORT_DENY_FLAG
) || m
== NULL
) {
916 ip
= mtod(m
, struct ip
*);
917 if (off
== 0 && dst
== old
) {/* common case */
918 lck_mtx_lock(ip_mutex
);
922 if (DUMMYNET_LOADED
&& (off
& IP_FW_PORT_DYNT_FLAG
) != 0) {
924 * pass the pkt to dummynet. Need to include
925 * pipe number, m, ifp, ro, dst because these are
926 * not recomputed in the next pass.
927 * All other parameters have been already used and
928 * so they are not needed anymore.
929 * XXX note: if the ifp or ro entry are deleted
930 * while a pkt is in dummynet, we are in trouble!
936 error
= ip_dn_io_ptr(m
, off
& 0xffff, DN_TO_IP_OUT
,
940 #endif /* DUMMYNET */
941 lck_mtx_lock(ip_mutex
);
943 if (off
!= 0 && (off
& IP_FW_PORT_DYNT_FLAG
) == 0) {
944 struct mbuf
*clone
= NULL
;
946 /* Clone packet if we're doing a 'tee' */
947 if ((off
& IP_FW_PORT_TEE_FLAG
) != 0)
948 clone
= m_dup(m
, M_DONTWAIT
);
951 * delayed checksums are not currently compatible
952 * with divert sockets.
954 if (m
->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA
) {
956 m
->m_pkthdr
.csum_flags
&= ~CSUM_DELAY_DATA
;
959 /* Restore packet header fields to original values */
963 /* Deliver packet to divert input routine */
964 divert_packet(m
, 0, off
& 0xffff, args
.divert_rule
);
966 /* If 'tee', continue with original packet */
969 ip
= mtod(m
, struct ip
*);
972 lck_mtx_unlock(ip_mutex
);
977 #if IPFIREWALL_FORWARD
978 /* Here we check dst to make sure it's directly reachable on the
979 * interface we previously thought it was.
980 * If it isn't (which may be likely in some situations) we have
981 * to re-route it (ie, find a route for the next-hop and the
982 * associated interface) and set them here. This is nested
983 * forwarding which in most cases is undesirable, except where
984 * such control is nigh impossible. So we do it here.
987 if (off
== 0 && old
!= dst
) {
988 struct in_ifaddr
*ia_fw
;
990 /* It's changed... */
991 /* There must be a better way to do this next line... */
992 static struct route sro_fwd
, *ro_fwd
= &sro_fwd
;
993 #if IPFIREWALL_FORWARD_DEBUG
994 printf("IPFIREWALL_FORWARD: New dst ip: ");
995 print_ip(dst
->sin_addr
);
999 * We need to figure out if we have been forwarded
1000 * to a local socket. If so then we should somehow
1001 * "loop back" to ip_input, and get directed to the
1002 * PCB as if we had received this packet. This is
1003 * because it may be dificult to identify the packets
1004 * you want to forward until they are being output
1005 * and have selected an interface. (e.g. locally
1006 * initiated packets) If we used the loopback inteface,
1007 * we would not be able to control what happens
1008 * as the packet runs through ip_input() as
1009 * it is done through a ISR.
1011 TAILQ_FOREACH(ia_fw
, &in_ifaddrhead
, ia_link
) {
1013 * If the addr to forward to is one
1014 * of ours, we pretend to
1015 * be the destination for this packet.
1017 if (IA_SIN(ia_fw
)->sin_addr
.s_addr
==
1018 dst
->sin_addr
.s_addr
)
1022 /* tell ip_input "dont filter" */
1023 struct m_tag
*fwd_tag
;
1024 struct ip_fwd_tag
*ipfwd_tag
;
1026 fwd_tag
= m_tag_alloc(KERNEL_MODULE_TAG_ID
, KERNEL_TAG_TYPE_IPFORWARD
,
1027 sizeof(struct sockaddr_in
), M_NOWAIT
);
1028 if (fwd_tag
== NULL
) {
1033 ipfwd_tag
= (struct ip_fwd_tag
*)(fwd_tag
+1);
1034 ipfwd_tag
->next_hop
= args
.next_hop
;
1036 m_tag_prepend(m
, fwd_tag
);
1038 if (m
->m_pkthdr
.rcvif
== NULL
)
1039 m
->m_pkthdr
.rcvif
= ifunit("lo0");
1040 if ((~IF_HWASSIST_CSUM_FLAGS(m
->m_pkthdr
.rcvif
->if_hwassist
) &
1041 m
->m_pkthdr
.csum_flags
) == 0) {
1042 if (m
->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA
) {
1043 m
->m_pkthdr
.csum_flags
&= ~CSUM_DELAY_DATA
;
1044 m
->m_pkthdr
.csum_flags
|=
1045 CSUM_DATA_VALID
| CSUM_PSEUDO_HDR
;
1046 m
->m_pkthdr
.csum_data
= 0xffff;
1048 m
->m_pkthdr
.csum_flags
|=
1049 CSUM_IP_CHECKED
| CSUM_IP_VALID
;
1051 else if (m
->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA
) {
1052 in_delayed_cksum(m
);
1053 m
->m_pkthdr
.csum_flags
&= ~CSUM_DELAY_DATA
;
1054 ip
->ip_sum
= in_cksum(m
, hlen
);
1059 lck_mtx_unlock(ip_mutex
);
1061 /* we need to call dlil_output to run filters
1062 * and resync to avoid recursion loops.
1065 dlil_output(lo_ifp
, PF_INET
, m
, 0, (struct sockaddr
*)dst
, 0);
1068 printf("ip_output: no loopback ifp for forwarding!!!\n");
1072 /* Some of the logic for this was
1073 * nicked from above.
1075 * This rewrites the cached route in a local PCB.
1076 * Is this what we want to do?
1078 bcopy(dst
, &ro_fwd
->ro_dst
, sizeof(*dst
));
1081 rtalloc_ign(ro_fwd
, RTF_PRCLONING
);
1083 if (ro_fwd
->ro_rt
== 0) {
1084 ipstat
.ips_noroute
++;
1085 error
= EHOSTUNREACH
;
1089 ia_fw
= ifatoia(ro_fwd
->ro_rt
->rt_ifa
);
1090 ifp
= ro_fwd
->ro_rt
->rt_ifp
;
1091 ro_fwd
->ro_rt
->rt_use
++;
1092 if (ro_fwd
->ro_rt
->rt_flags
& RTF_GATEWAY
)
1093 dst
= (struct sockaddr_in
*)ro_fwd
->ro_rt
->rt_gateway
;
1094 if (ro_fwd
->ro_rt
->rt_flags
& RTF_HOST
)
1096 (ro_fwd
->ro_rt
->rt_flags
& RTF_BROADCAST
);
1098 isbroadcast
= in_broadcast(dst
->sin_addr
, ifp
);
1100 ro
->ro_rt
= ro_fwd
->ro_rt
;
1101 dst
= (struct sockaddr_in
*)&ro_fwd
->ro_dst
;
1104 * If we added a default src ip earlier,
1105 * which would have been gotten from the-then
1106 * interface, do it again, from the new one.
1108 if (fwd_rewrite_src
)
1109 ip
->ip_src
= IA_SIN(ia_fw
)->sin_addr
;
1112 #endif /* IPFIREWALL_FORWARD */
1114 * if we get here, none of the above matches, and
1115 * we have to drop the pkt
1118 error
= EACCES
; /* not sure this is the right error msg */
1119 lck_mtx_unlock(ip_mutex
);
1125 /* Do not allow loopback address to wind up on a wire */
1126 if ((ifp
->if_flags
& IFF_LOOPBACK
) == 0 &&
1127 ((ntohl(ip
->ip_src
.s_addr
) >> IN_CLASSA_NSHIFT
) == IN_LOOPBACKNET
||
1128 (ntohl(ip
->ip_dst
.s_addr
) >> IN_CLASSA_NSHIFT
) == IN_LOOPBACKNET
)) {
1129 ipstat
.ips_badaddr
++;
1132 * Do not simply drop the packet just like a firewall -- we want the
1133 * the application to feel the pain.
1134 * Return ENETUNREACH like ip6_output does in some similar cases.
1135 * This can startle the otherwise clueless process that specifies
1136 * loopback as the source address.
1138 error
= ENETUNREACH
;
1139 lck_mtx_unlock(ip_mutex
);
1143 m
->m_pkthdr
.csum_flags
|= CSUM_IP
;
1144 sw_csum
= m
->m_pkthdr
.csum_flags
1145 & ~IF_HWASSIST_CSUM_FLAGS(ifp
->if_hwassist
);
1147 if ((ifp
->if_hwassist
& CSUM_TCP_SUM16
) != 0) {
1149 * Special case code for GMACE
1150 * frames that can be checksumed by GMACE SUM16 HW:
1151 * frame >64, no fragments, no UDP
1153 if (apple_hwcksum_tx
&& (m
->m_pkthdr
.csum_flags
& CSUM_TCP
)
1154 && (ip
->ip_len
> 50) && (ip
->ip_len
<= ifp
->if_mtu
)) {
1155 /* Apple GMAC HW, expects STUFF_OFFSET << 16 | START_OFFSET */
1156 u_short offset
= (IP_VHL_HL(ip
->ip_vhl
) << 2) +14 ; /* IP+Enet header length */
1157 u_short csumprev
= m
->m_pkthdr
.csum_data
& 0xFFFF;
1158 m
->m_pkthdr
.csum_flags
= CSUM_DATA_VALID
| CSUM_TCP_SUM16
; /* for GMAC */
1159 m
->m_pkthdr
.csum_data
= (csumprev
+ offset
) << 16 ;
1160 m
->m_pkthdr
.csum_data
+= offset
;
1161 sw_csum
= CSUM_DELAY_IP
; /* do IP hdr chksum in software */
1164 /* let the software handle any UDP or TCP checksums */
1165 sw_csum
|= (CSUM_DELAY_DATA
& m
->m_pkthdr
.csum_flags
);
1169 if (sw_csum
& CSUM_DELAY_DATA
) {
1170 in_delayed_cksum(m
);
1171 sw_csum
&= ~CSUM_DELAY_DATA
;
1172 m
->m_pkthdr
.csum_flags
&= ~CSUM_DELAY_DATA
;
1175 m
->m_pkthdr
.csum_flags
&= IF_HWASSIST_CSUM_FLAGS(ifp
->if_hwassist
);
1178 * If small enough for interface, or the interface will take
1179 * care of the fragmentation for us, can just send directly.
1181 if ((u_short
)ip
->ip_len
<= ifp
->if_mtu
||
1182 ifp
->if_hwassist
& CSUM_FRAGMENT
) {
1186 if (sw_csum
& CSUM_DELAY_IP
) {
1187 ip
->ip_sum
= in_cksum(m
, hlen
);
1191 /* Record statistics for this interface address. */
1192 if (!(flags
& IP_FORWARDING
) && ia
!= NULL
) {
1193 ia
->ia_ifa
.if_opackets
++;
1194 ia
->ia_ifa
.if_obytes
+= m
->m_pkthdr
.len
;
1199 /* clean ipsec history once it goes out of the node */
1200 if (ipsec_bypass
== 0 && (flags
& IP_NOIPSEC
) == 0)
1203 if (packetchain
== 0) {
1204 lck_mtx_unlock(ip_mutex
);
1205 error
= dlil_output(ifp
, PF_INET
, m
, (void *) ro
->ro_rt
,
1206 (struct sockaddr
*)dst
, 0);
1209 else { /* packet chaining allows us to reuse the route for all packets */
1212 if (pktcnt
> ip_maxchainsent
)
1213 ip_maxchainsent
= pktcnt
;
1215 lck_mtx_unlock(ip_mutex
);
1216 error
= dlil_output_list(ifp
, PF_INET
, packetlist
, (void *) ro
->ro_rt
,
1217 (struct sockaddr
*)dst
, 0);
1228 * Too large for interface; fragment if possible.
1229 * Must be able to put at least 8 bytes per fragment.
1231 if (ip
->ip_off
& IP_DF
) {
1234 * This case can happen if the user changed the MTU
1235 * of an interface after enabling IP on it. Because
1236 * most netifs don't keep track of routes pointing to
1237 * them, there is no way for one to update all its
1238 * routes when the MTU is changed.
1240 if (ro
->ro_rt
&& (ro
->ro_rt
->rt_flags
& (RTF_UP
| RTF_HOST
))
1241 && !(ro
->ro_rt
->rt_rmx
.rmx_locks
& RTV_MTU
)
1242 && (ro
->ro_rt
->rt_rmx
.rmx_mtu
> ifp
->if_mtu
)) {
1243 ro
->ro_rt
->rt_rmx
.rmx_mtu
= ifp
->if_mtu
;
1245 ipstat
.ips_cantfrag
++;
1248 len
= (ifp
->if_mtu
- hlen
) &~ 7;
1255 * if the interface will not calculate checksums on
1256 * fragmented packets, then do it here.
1258 if (m
->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA
&&
1259 (ifp
->if_hwassist
& CSUM_IP_FRAGS
) == 0) {
1260 in_delayed_cksum(m
);
1262 lck_mtx_unlock(ip_mutex
);
1265 m
->m_pkthdr
.csum_flags
&= ~CSUM_DELAY_DATA
;
1270 int mhlen
, firstlen
= len
;
1271 struct mbuf
**mnext
= &m
->m_nextpkt
;
1275 * Loop through length of segment after first fragment,
1276 * make new header and copy data of each part and link onto chain.
1279 mhlen
= sizeof (struct ip
);
1280 for (off
= hlen
+ len
; off
< (u_short
)ip
->ip_len
; off
+= len
) {
1281 MGETHDR(m
, M_DONTWAIT
, MT_HEADER
);
1284 ipstat
.ips_odropped
++;
1287 m
->m_flags
|= (m0
->m_flags
& M_MCAST
) | M_FRAG
;
1288 m
->m_data
+= max_linkhdr
;
1289 mhip
= mtod(m
, struct ip
*);
1291 if (hlen
> sizeof (struct ip
)) {
1292 mhlen
= ip_optcopy(ip
, mhip
) + sizeof (struct ip
);
1293 mhip
->ip_vhl
= IP_MAKE_VHL(IPVERSION
, mhlen
>> 2);
1296 mhip
->ip_off
= ((off
- hlen
) >> 3) + (ip
->ip_off
& ~IP_MF
);
1297 if (ip
->ip_off
& IP_MF
)
1298 mhip
->ip_off
|= IP_MF
;
1299 if (off
+ len
>= (u_short
)ip
->ip_len
)
1300 len
= (u_short
)ip
->ip_len
- off
;
1302 mhip
->ip_off
|= IP_MF
;
1303 mhip
->ip_len
= htons((u_short
)(len
+ mhlen
));
1304 m
->m_next
= m_copy(m0
, off
, len
);
1305 if (m
->m_next
== 0) {
1307 error
= ENOBUFS
; /* ??? */
1308 ipstat
.ips_odropped
++;
1311 m
->m_pkthdr
.len
= mhlen
+ len
;
1312 m
->m_pkthdr
.rcvif
= 0;
1313 m
->m_pkthdr
.csum_flags
= m0
->m_pkthdr
.csum_flags
;
1314 m
->m_pkthdr
.socket_id
= m0
->m_pkthdr
.socket_id
;
1315 HTONS(mhip
->ip_off
);
1317 if (sw_csum
& CSUM_DELAY_IP
) {
1318 mhip
->ip_sum
= in_cksum(m
, mhlen
);
1321 mnext
= &m
->m_nextpkt
;
1324 ipstat
.ips_ofragments
+= nfrags
;
1326 /* set first/last markers for fragment chain */
1327 m
->m_flags
|= M_LASTFRAG
;
1328 m0
->m_flags
|= M_FIRSTFRAG
| M_FRAG
;
1329 m0
->m_pkthdr
.csum_data
= nfrags
;
1332 * Update first fragment by trimming what's been copied out
1333 * and updating header, then send each fragment (in order).
1336 m_adj(m
, hlen
+ firstlen
- (u_short
)ip
->ip_len
);
1337 m
->m_pkthdr
.len
= hlen
+ firstlen
;
1338 ip
->ip_len
= htons((u_short
)m
->m_pkthdr
.len
);
1339 ip
->ip_off
|= IP_MF
;
1342 if (sw_csum
& CSUM_DELAY_IP
) {
1343 ip
->ip_sum
= in_cksum(m
, hlen
);
1347 KERNEL_DEBUG(DBG_LAYER_END
, ip
->ip_dst
.s_addr
,
1348 ip
->ip_src
.s_addr
, ip
->ip_p
, ip
->ip_off
, ip
->ip_len
);
1350 lck_mtx_unlock(ip_mutex
);
1351 for (m
= m0
; m
; m
= m0
) {
1355 /* clean ipsec history once it goes out of the node */
1356 if (ipsec_bypass
== 0 && (flags
& IP_NOIPSEC
) == 0)
1361 /* Record statistics for this interface address. */
1363 ia
->ia_ifa
.if_opackets
++;
1364 ia
->ia_ifa
.if_obytes
+= m
->m_pkthdr
.len
;
1367 if ((packetchain
!= 0) && (pktcnt
> 0))
1368 panic("ip_output: mix of packet in packetlist is wrong=%x", packetlist
);
1369 error
= dlil_output(ifp
, PF_INET
, m
, (void *) ro
->ro_rt
,
1370 (struct sockaddr
*)dst
, 0);
1376 ipstat
.ips_fragmented
++;
1380 ifafree(&ia
->ia_ifa
);
1384 if (ipsec_bypass
== 0 && (flags
& IP_NOIPSEC
) == 0) {
1385 if (ro
== &iproute
&& ro
->ro_rt
) {
1390 KEYDEBUG(KEYDEBUG_IPSEC_STAMP
,
1391 printf("DP ip_output call free SP:%x\n", sp
));
1392 lck_mtx_lock(sadb_mutex
);
1394 lck_mtx_unlock(sadb_mutex
);
1399 KERNEL_DEBUG(DBG_FNC_IP_OUTPUT
| DBG_FUNC_END
, error
,0,0,0,0);
1403 lck_mtx_unlock(ip_mutex
);
1408 in_delayed_cksum_offset(struct mbuf
*m0
, int ip_offset
)
1411 unsigned char buf
[sizeof(struct ip
)];
1412 u_short csum
, offset
, ip_len
;
1413 struct mbuf
*m
= m0
;
1415 while (ip_offset
>= m
->m_len
) {
1416 ip_offset
-= m
->m_len
;
1419 printf("in_delayed_cksum_offset failed - ip_offset wasn't in the packet\n");
1424 /* Sometimes the IP header is not contiguous, yes this can happen! */
1425 if (ip_offset
+ sizeof(struct ip
) > m
->m_len
) {
1427 printf("delayed m_pullup, m->len: %d off: %d\n",
1428 m
->m_len
, ip_offset
);
1430 m_copydata(m
, ip_offset
, sizeof(struct ip
), buf
);
1432 ip
= (struct ip
*)buf
;
1434 ip
= (struct ip
*)(m
->m_data
+ ip_offset
);
1439 m
->m_len
-= ip_offset
;
1440 m
->m_data
+= ip_offset
;
1443 offset
= IP_VHL_HL(ip
->ip_vhl
) << 2 ;
1446 * We could be in the context of an IP or interface filter; in the
1447 * former case, ip_len would be in host (correct) order while for
1448 * the latter it would be in network order. Because of this, we
1449 * attempt to interpret the length field by comparing it against
1450 * the actual packet length. If the comparison fails, byte swap
1451 * the length and check again. If it still fails, then the packet
1452 * is bogus and we give up.
1454 ip_len
= ip
->ip_len
;
1455 if (ip_len
!= (m0
->m_pkthdr
.len
- ip_offset
)) {
1456 ip_len
= SWAP16(ip_len
);
1457 if (ip_len
!= (m0
->m_pkthdr
.len
- ip_offset
)) {
1458 printf("in_delayed_cksum_offset: ip_len %d (%d) "
1459 "doesn't match actual length %d\n", ip
->ip_len
,
1460 ip_len
, (m0
->m_pkthdr
.len
- ip_offset
));
1465 csum
= in_cksum_skip(m
, ip_len
, offset
);
1467 if (m0
->m_pkthdr
.csum_flags
& CSUM_UDP
&& csum
== 0)
1469 offset
+= m0
->m_pkthdr
.csum_data
& 0xFFFF; /* checksum offset */
1473 if (M_LEADINGSPACE(m
) < ip_offset
)
1474 panic("in_delayed_cksum_offset - chain modified!\n");
1475 m
->m_len
+= ip_offset
;
1476 m
->m_data
-= ip_offset
;
1479 if (offset
> ip_len
) /* bogus offset */
1482 /* Insert the checksum in the existing chain */
1483 if (offset
+ ip_offset
+ sizeof(u_short
) > m
->m_len
) {
1487 printf("delayed m_copyback, m->len: %d off: %d p: %d\n",
1488 m
->m_len
, offset
+ ip_offset
, ip
->ip_p
);
1490 *(u_short
*)tmp
= csum
;
1491 m_copyback(m
, offset
+ ip_offset
, 2, tmp
);
1493 *(u_short
*)(m
->m_data
+ offset
+ ip_offset
) = csum
;
1497 in_delayed_cksum(struct mbuf
*m
)
1499 in_delayed_cksum_offset(m
, 0);
1503 in_cksum_offset(struct mbuf
* m
, size_t ip_offset
)
1505 struct ip
* ip
= NULL
;
1507 unsigned char buf
[sizeof(struct ip
)];
1510 while (ip_offset
>= m
->m_len
) {
1511 ip_offset
-= m
->m_len
;
1514 printf("in_cksum_offset failed - ip_offset wasn't in the packet\n");
1519 /* Sometimes the IP header is not contiguous, yes this can happen! */
1520 if (ip_offset
+ sizeof(struct ip
) > m
->m_len
) {
1523 printf("in_cksum_offset - delayed m_pullup, m->len: %d off: %d\n",
1524 m
->m_len
, ip_offset
);
1526 m_copydata(m
, ip_offset
, sizeof(struct ip
), buf
);
1528 ip
= (struct ip
*)buf
;
1530 m_copyback(m
, ip_offset
+ offsetof(struct ip
, ip_sum
), 2, (caddr_t
)&ip
->ip_sum
);
1532 ip
= (struct ip
*)(m
->m_data
+ ip_offset
);
1538 m
->m_len
-= ip_offset
;
1539 m
->m_data
+= ip_offset
;
1543 hlen
= IP_VHL_HL(ip
->ip_vhl
) << 2;
1545 hlen
= ip
->ip_hl
<< 2;
1548 * We could be in the context of an IP or interface filter; in the
1549 * former case, ip_len would be in host order while for the latter
1550 * it would be in network (correct) order. Because of this, we
1551 * attempt to interpret the length field by comparing it against
1552 * the actual packet length. If the comparison fails, byte swap
1553 * the length and check again. If it still fails, then the packet
1554 * is bogus and we give up.
1556 if (ntohs(ip
->ip_len
) != (m
->m_pkthdr
.len
- ip_offset
)) {
1557 ip
->ip_len
= SWAP16(ip
->ip_len
);
1559 if (ntohs(ip
->ip_len
) != (m
->m_pkthdr
.len
- ip_offset
)) {
1560 ip
->ip_len
= SWAP16(ip
->ip_len
);
1561 printf("in_cksum_offset: ip_len %d (%d) "
1562 "doesn't match actual length %d\n",
1563 ip
->ip_len
, SWAP16(ip
->ip_len
),
1564 (m
->m_pkthdr
.len
- ip_offset
));
1570 ip
->ip_sum
= in_cksum(m
, hlen
);
1572 ip
->ip_len
= SWAP16(ip
->ip_len
);
1576 if (M_LEADINGSPACE(m
) < ip_offset
)
1577 panic("in_cksum_offset - chain modified!\n");
1578 m
->m_len
+= ip_offset
;
1579 m
->m_data
-= ip_offset
;
1582 /* Insert the checksum in the existing chain if IP header not contiguous */
1583 if (ip_offset
+ sizeof(struct ip
) > m
->m_len
) {
1587 printf("in_cksum_offset m_copyback, m->len: %d off: %d p: %d\n",
1588 m
->m_len
, ip_offset
+ offsetof(struct ip
, ip_sum
), ip
->ip_p
);
1590 *(u_short
*)tmp
= ip
->ip_sum
;
1591 m_copyback(m
, ip_offset
+ offsetof(struct ip
, ip_sum
), 2, tmp
);
1596 * Insert IP options into preformed packet.
1597 * Adjust IP destination as required for IP source routing,
1598 * as indicated by a non-zero in_addr at the start of the options.
1600 * XXX This routine assumes that the packet has no options in place.
1602 static struct mbuf
*
1603 ip_insertoptions(m
, opt
, phlen
)
1604 register struct mbuf
*m
;
1608 register struct ipoption
*p
= mtod(opt
, struct ipoption
*);
1610 register struct ip
*ip
= mtod(m
, struct ip
*);
1613 optlen
= opt
->m_len
- sizeof(p
->ipopt_dst
);
1614 if (optlen
+ (u_short
)ip
->ip_len
> IP_MAXPACKET
)
1615 return (m
); /* XXX should fail */
1616 if (p
->ipopt_dst
.s_addr
)
1617 ip
->ip_dst
= p
->ipopt_dst
;
1618 if (m
->m_flags
& M_EXT
|| m
->m_data
- optlen
< m
->m_pktdat
) {
1619 MGETHDR(n
, M_DONTWAIT
, MT_HEADER
);
1622 n
->m_pkthdr
.rcvif
= 0;
1623 n
->m_pkthdr
.len
= m
->m_pkthdr
.len
+ optlen
;
1624 m
->m_len
-= sizeof(struct ip
);
1625 m
->m_data
+= sizeof(struct ip
);
1628 m
->m_len
= optlen
+ sizeof(struct ip
);
1629 m
->m_data
+= max_linkhdr
;
1630 (void)memcpy(mtod(m
, void *), ip
, sizeof(struct ip
));
1632 m
->m_data
-= optlen
;
1634 m
->m_pkthdr
.len
+= optlen
;
1635 ovbcopy((caddr_t
)ip
, mtod(m
, caddr_t
), sizeof(struct ip
));
1637 ip
= mtod(m
, struct ip
*);
1638 bcopy(p
->ipopt_list
, ip
+ 1, optlen
);
1639 *phlen
= sizeof(struct ip
) + optlen
;
1640 ip
->ip_vhl
= IP_MAKE_VHL(IPVERSION
, *phlen
>> 2);
1641 ip
->ip_len
+= optlen
;
1646 * Copy options from ip to jp,
1647 * omitting those not copied during fragmentation.
1653 register u_char
*cp
, *dp
;
1654 int opt
, optlen
, cnt
;
1656 cp
= (u_char
*)(ip
+ 1);
1657 dp
= (u_char
*)(jp
+ 1);
1658 cnt
= (IP_VHL_HL(ip
->ip_vhl
) << 2) - sizeof (struct ip
);
1659 for (; cnt
> 0; cnt
-= optlen
, cp
+= optlen
) {
1661 if (opt
== IPOPT_EOL
)
1663 if (opt
== IPOPT_NOP
) {
1664 /* Preserve for IP mcast tunnel's LSRR alignment. */
1670 if (cnt
< IPOPT_OLEN
+ sizeof(*cp
))
1671 panic("malformed IPv4 option passed to ip_optcopy");
1673 optlen
= cp
[IPOPT_OLEN
];
1675 if (optlen
< IPOPT_OLEN
+ sizeof(*cp
) || optlen
> cnt
)
1676 panic("malformed IPv4 option passed to ip_optcopy");
1678 /* bogus lengths should have been caught by ip_dooptions */
1681 if (IPOPT_COPIED(opt
)) {
1682 bcopy(cp
, dp
, optlen
);
1686 for (optlen
= dp
- (u_char
*)(jp
+1); optlen
& 0x3; optlen
++)
1692 * IP socket option processing.
1695 ip_ctloutput(so
, sopt
)
1697 struct sockopt
*sopt
;
1699 struct inpcb
*inp
= sotoinpcb(so
);
1703 if (sopt
->sopt_level
!= IPPROTO_IP
) {
1707 switch (sopt
->sopt_dir
) {
1709 switch (sopt
->sopt_name
) {
1716 if (sopt
->sopt_valsize
> MLEN
) {
1720 MGET(m
, sopt
->sopt_p
? M_WAIT
: M_DONTWAIT
, MT_HEADER
);
1725 m
->m_len
= sopt
->sopt_valsize
;
1726 error
= sooptcopyin(sopt
, mtod(m
, char *), m
->m_len
,
1731 return (ip_pcbopts(sopt
->sopt_name
, &inp
->inp_options
,
1738 case IP_RECVRETOPTS
:
1739 case IP_RECVDSTADDR
:
1742 #if defined(NFAITH) && NFAITH > 0
1745 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
1750 switch (sopt
->sopt_name
) {
1752 inp
->inp_ip_tos
= optval
;
1756 inp
->inp_ip_ttl
= optval
;
1758 #define OPTSET(bit) \
1760 inp->inp_flags |= bit; \
1762 inp->inp_flags &= ~bit;
1765 OPTSET(INP_RECVOPTS
);
1768 case IP_RECVRETOPTS
:
1769 OPTSET(INP_RECVRETOPTS
);
1772 case IP_RECVDSTADDR
:
1773 OPTSET(INP_RECVDSTADDR
);
1781 OPTSET(INP_RECVTTL
);
1784 #if defined(NFAITH) && NFAITH > 0
1793 case IP_MULTICAST_IF
:
1794 case IP_MULTICAST_VIF
:
1795 case IP_MULTICAST_TTL
:
1796 case IP_MULTICAST_LOOP
:
1797 case IP_ADD_MEMBERSHIP
:
1798 case IP_DROP_MEMBERSHIP
:
1799 error
= ip_setmoptions(sopt
, &inp
->inp_moptions
);
1803 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
1809 case IP_PORTRANGE_DEFAULT
:
1810 inp
->inp_flags
&= ~(INP_LOWPORT
);
1811 inp
->inp_flags
&= ~(INP_HIGHPORT
);
1814 case IP_PORTRANGE_HIGH
:
1815 inp
->inp_flags
&= ~(INP_LOWPORT
);
1816 inp
->inp_flags
|= INP_HIGHPORT
;
1819 case IP_PORTRANGE_LOW
:
1820 inp
->inp_flags
&= ~(INP_HIGHPORT
);
1821 inp
->inp_flags
|= INP_LOWPORT
;
1831 case IP_IPSEC_POLICY
:
1839 if (sopt
->sopt_valsize
> MCLBYTES
) {
1843 if ((error
= soopt_getm(sopt
, &m
)) != 0) /* XXX */
1845 if ((error
= soopt_mcopyin(sopt
, m
)) != 0) /* XXX */
1847 priv
= (sopt
->sopt_p
!= NULL
&&
1848 proc_suser(sopt
->sopt_p
) != 0) ? 0 : 1;
1850 req
= mtod(m
, caddr_t
);
1853 optname
= sopt
->sopt_name
;
1854 lck_mtx_lock(sadb_mutex
);
1855 error
= ipsec4_set_policy(inp
, optname
, req
, len
, priv
);
1856 lck_mtx_unlock(sadb_mutex
);
1863 error
= ENOPROTOOPT
;
1869 switch (sopt
->sopt_name
) {
1872 if (inp
->inp_options
)
1873 error
= sooptcopyout(sopt
,
1874 mtod(inp
->inp_options
,
1876 inp
->inp_options
->m_len
);
1878 sopt
->sopt_valsize
= 0;
1884 case IP_RECVRETOPTS
:
1885 case IP_RECVDSTADDR
:
1889 #if defined(NFAITH) && NFAITH > 0
1892 switch (sopt
->sopt_name
) {
1895 optval
= inp
->inp_ip_tos
;
1899 optval
= inp
->inp_ip_ttl
;
1902 #define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0)
1905 optval
= OPTBIT(INP_RECVOPTS
);
1908 case IP_RECVRETOPTS
:
1909 optval
= OPTBIT(INP_RECVRETOPTS
);
1912 case IP_RECVDSTADDR
:
1913 optval
= OPTBIT(INP_RECVDSTADDR
);
1917 optval
= OPTBIT(INP_RECVIF
);
1921 optval
= OPTBIT(INP_RECVTTL
);
1925 if (inp
->inp_flags
& INP_HIGHPORT
)
1926 optval
= IP_PORTRANGE_HIGH
;
1927 else if (inp
->inp_flags
& INP_LOWPORT
)
1928 optval
= IP_PORTRANGE_LOW
;
1933 #if defined(NFAITH) && NFAITH > 0
1935 optval
= OPTBIT(INP_FAITH
);
1939 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
1942 case IP_MULTICAST_IF
:
1943 case IP_MULTICAST_VIF
:
1944 case IP_MULTICAST_TTL
:
1945 case IP_MULTICAST_LOOP
:
1946 case IP_ADD_MEMBERSHIP
:
1947 case IP_DROP_MEMBERSHIP
:
1948 error
= ip_getmoptions(sopt
, inp
->inp_moptions
);
1952 case IP_IPSEC_POLICY
:
1954 struct mbuf
*m
= NULL
;
1959 req
= mtod(m
, caddr_t
);
1962 lck_mtx_lock(sadb_mutex
);
1963 error
= ipsec4_get_policy(sotoinpcb(so
), req
, len
, &m
);
1964 lck_mtx_unlock(sadb_mutex
);
1966 error
= soopt_mcopyout(sopt
, m
); /* XXX */
1974 error
= ENOPROTOOPT
;
1983 * Set up IP options in pcb for insertion in output packets.
1984 * Store in mbuf with pointer in pcbopt, adding pseudo-option
1985 * with destination address if source routed.
1988 ip_pcbopts(optname
, pcbopt
, m
)
1990 struct mbuf
**pcbopt
;
1991 register struct mbuf
*m
;
1993 register int cnt
, optlen
;
1994 register u_char
*cp
;
1997 /* turn off any old options */
1999 (void)m_free(*pcbopt
);
2001 if (m
== (struct mbuf
*)0 || m
->m_len
== 0) {
2003 * Only turning off any previous options.
2011 if (m
->m_len
% sizeof(int32_t))
2015 * IP first-hop destination address will be stored before
2016 * actual options; move other options back
2017 * and clear it when none present.
2019 if (m
->m_data
+ m
->m_len
+ sizeof(struct in_addr
) >= &m
->m_dat
[MLEN
])
2022 m
->m_len
+= sizeof(struct in_addr
);
2023 cp
= mtod(m
, u_char
*) + sizeof(struct in_addr
);
2024 ovbcopy(mtod(m
, caddr_t
), (caddr_t
)cp
, (unsigned)cnt
);
2025 bzero(mtod(m
, caddr_t
), sizeof(struct in_addr
));
2027 for (; cnt
> 0; cnt
-= optlen
, cp
+= optlen
) {
2028 opt
= cp
[IPOPT_OPTVAL
];
2029 if (opt
== IPOPT_EOL
)
2031 if (opt
== IPOPT_NOP
)
2034 if (cnt
< IPOPT_OLEN
+ sizeof(*cp
))
2036 optlen
= cp
[IPOPT_OLEN
];
2037 if (optlen
< IPOPT_OLEN
+ sizeof(*cp
) || optlen
> cnt
)
2048 * user process specifies route as:
2050 * D must be our final destination (but we can't
2051 * check that since we may not have connected yet).
2052 * A is first hop destination, which doesn't appear in
2053 * actual IP option, but is stored before the options.
2055 if (optlen
< IPOPT_MINOFF
- 1 + sizeof(struct in_addr
))
2057 m
->m_len
-= sizeof(struct in_addr
);
2058 cnt
-= sizeof(struct in_addr
);
2059 optlen
-= sizeof(struct in_addr
);
2060 cp
[IPOPT_OLEN
] = optlen
;
2062 * Move first hop before start of options.
2064 bcopy((caddr_t
)&cp
[IPOPT_OFFSET
+1], mtod(m
, caddr_t
),
2065 sizeof(struct in_addr
));
2067 * Then copy rest of options back
2068 * to close up the deleted entry.
2070 ovbcopy((caddr_t
)(&cp
[IPOPT_OFFSET
+1] +
2071 sizeof(struct in_addr
)),
2072 (caddr_t
)&cp
[IPOPT_OFFSET
+1],
2073 (unsigned)cnt
+ sizeof(struct in_addr
));
2077 if (m
->m_len
> MAX_IPOPTLEN
+ sizeof(struct in_addr
))
2089 * The whole multicast option thing needs to be re-thought.
2090 * Several of these options are equally applicable to non-multicast
2091 * transmission, and one (IP_MULTICAST_TTL) totally duplicates a
2092 * standard option (IP_TTL).
2096 * following RFC1724 section 3.3, 0.0.0.0/8 is interpreted as interface index.
2098 static struct ifnet
*
2099 ip_multicast_if(a
, ifindexp
)
2108 if (ntohl(a
->s_addr
) >> 24 == 0) {
2109 ifindex
= ntohl(a
->s_addr
) & 0xffffff;
2110 ifnet_head_lock_shared();
2111 if (ifindex
< 0 || if_index
< ifindex
) {
2115 ifp
= ifindex2ifnet
[ifindex
];
2118 *ifindexp
= ifindex
;
2120 INADDR_TO_IFP(*a
, ifp
);
2126 * Set the IP multicast options in response to user setsockopt().
2129 ip_setmoptions(sopt
, imop
)
2130 struct sockopt
*sopt
;
2131 struct ip_moptions
**imop
;
2135 struct in_addr addr
;
2136 struct ip_mreq mreq
;
2137 struct ifnet
*ifp
= NULL
;
2138 struct ip_moptions
*imo
= *imop
;
2143 * No multicast option buffer attached to the pcb;
2144 * allocate one and initialize to default values.
2146 error
= ip_createmoptions(imop
);
2152 switch (sopt
->sopt_name
) {
2153 /* store an index number for the vif you wanna use in the send */
2154 case IP_MULTICAST_VIF
:
2155 if (legal_vif_num
== 0) {
2159 error
= sooptcopyin(sopt
, &i
, sizeof i
, sizeof i
);
2162 if (!legal_vif_num(i
) && (i
!= -1)) {
2166 imo
->imo_multicast_vif
= i
;
2169 case IP_MULTICAST_IF
:
2171 * Select the interface for outgoing multicast packets.
2173 error
= sooptcopyin(sopt
, &addr
, sizeof addr
, sizeof addr
);
2177 * INADDR_ANY is used to remove a previous selection.
2178 * When no interface is selected, a default one is
2179 * chosen every time a multicast packet is sent.
2181 if (addr
.s_addr
== INADDR_ANY
) {
2182 imo
->imo_multicast_ifp
= NULL
;
2186 * The selected interface is identified by its local
2187 * IP address. Find the interface and confirm that
2188 * it supports multicasting.
2190 ifp
= ip_multicast_if(&addr
, &ifindex
);
2191 if (ifp
== NULL
|| (ifp
->if_flags
& IFF_MULTICAST
) == 0) {
2192 error
= EADDRNOTAVAIL
;
2195 imo
->imo_multicast_ifp
= ifp
;
2197 imo
->imo_multicast_addr
= addr
;
2199 imo
->imo_multicast_addr
.s_addr
= INADDR_ANY
;
2202 case IP_MULTICAST_TTL
:
2204 * Set the IP time-to-live for outgoing multicast packets.
2205 * The original multicast API required a char argument,
2206 * which is inconsistent with the rest of the socket API.
2207 * We allow either a char or an int.
2209 if (sopt
->sopt_valsize
== 1) {
2211 error
= sooptcopyin(sopt
, &ttl
, 1, 1);
2214 imo
->imo_multicast_ttl
= ttl
;
2217 error
= sooptcopyin(sopt
, &ttl
, sizeof ttl
,
2224 imo
->imo_multicast_ttl
= ttl
;
2228 case IP_MULTICAST_LOOP
:
2230 * Set the loopback flag for outgoing multicast packets.
2231 * Must be zero or one. The original multicast API required a
2232 * char argument, which is inconsistent with the rest
2233 * of the socket API. We allow either a char or an int.
2235 if (sopt
->sopt_valsize
== 1) {
2237 error
= sooptcopyin(sopt
, &loop
, 1, 1);
2240 imo
->imo_multicast_loop
= !!loop
;
2243 error
= sooptcopyin(sopt
, &loop
, sizeof loop
,
2247 imo
->imo_multicast_loop
= !!loop
;
2251 case IP_ADD_MEMBERSHIP
:
2253 * Add a multicast group membership.
2254 * Group must be a valid IP multicast address.
2256 error
= sooptcopyin(sopt
, &mreq
, sizeof mreq
, sizeof mreq
);
2260 error
= ip_addmembership(imo
, &mreq
);
2263 case IP_DROP_MEMBERSHIP
:
2265 * Drop a multicast group membership.
2266 * Group must be a valid IP multicast address.
2268 error
= sooptcopyin(sopt
, &mreq
, sizeof mreq
, sizeof mreq
);
2272 error
= ip_dropmembership(imo
, &mreq
);
2281 * If all options have default values, no need to keep the mbuf.
2283 if (imo
->imo_multicast_ifp
== NULL
&&
2284 imo
->imo_multicast_vif
== -1 &&
2285 imo
->imo_multicast_ttl
== IP_DEFAULT_MULTICAST_TTL
&&
2286 imo
->imo_multicast_loop
== IP_DEFAULT_MULTICAST_LOOP
&&
2287 imo
->imo_num_memberships
== 0) {
2288 FREE(*imop
, M_IPMOPTS
);
2296 * Set the IP multicast options in response to user setsockopt().
2298 __private_extern__
int
2300 struct ip_moptions
**imop
)
2302 struct ip_moptions
*imo
;
2303 imo
= (struct ip_moptions
*) _MALLOC(sizeof(*imo
), M_IPMOPTS
,
2309 imo
->imo_multicast_ifp
= NULL
;
2310 imo
->imo_multicast_addr
.s_addr
= INADDR_ANY
;
2311 imo
->imo_multicast_vif
= -1;
2312 imo
->imo_multicast_ttl
= IP_DEFAULT_MULTICAST_TTL
;
2313 imo
->imo_multicast_loop
= IP_DEFAULT_MULTICAST_LOOP
;
2314 imo
->imo_num_memberships
= 0;
2320 * Add membership to an IPv4 multicast.
2322 __private_extern__
int
2324 struct ip_moptions
*imo
,
2325 struct ip_mreq
*mreq
)
2328 struct sockaddr_in
*dst
;
2329 struct ifnet
*ifp
= NULL
;
2333 if (!IN_MULTICAST(ntohl(mreq
->imr_multiaddr
.s_addr
))) {
2338 * If no interface address was provided, use the interface of
2339 * the route to the given multicast address.
2341 if (mreq
->imr_interface
.s_addr
== INADDR_ANY
) {
2342 bzero((caddr_t
)&ro
, sizeof(ro
));
2343 dst
= (struct sockaddr_in
*)&ro
.ro_dst
;
2344 dst
->sin_len
= sizeof(*dst
);
2345 dst
->sin_family
= AF_INET
;
2346 dst
->sin_addr
= mreq
->imr_multiaddr
;
2348 if (ro
.ro_rt
!= NULL
) {
2349 ifp
= ro
.ro_rt
->rt_ifp
;
2353 /* If there's no default route, try using loopback */
2354 mreq
->imr_interface
.s_addr
= INADDR_LOOPBACK
;
2359 ifp
= ip_multicast_if(&mreq
->imr_interface
, NULL
);
2363 * See if we found an interface, and confirm that it
2364 * supports multicast.
2366 if (ifp
== NULL
|| (ifp
->if_flags
& IFF_MULTICAST
) == 0) {
2367 error
= EADDRNOTAVAIL
;
2371 * See if the membership already exists or if all the
2372 * membership slots are full.
2374 for (i
= 0; i
< imo
->imo_num_memberships
; ++i
) {
2375 if (imo
->imo_membership
[i
]->inm_ifp
== ifp
&&
2376 imo
->imo_membership
[i
]->inm_addr
.s_addr
2377 == mreq
->imr_multiaddr
.s_addr
)
2380 if (i
< imo
->imo_num_memberships
) {
2384 if (i
== IP_MAX_MEMBERSHIPS
) {
2385 error
= ETOOMANYREFS
;
2389 * Everything looks good; add a new record to the multicast
2390 * address list for the given interface.
2392 if ((imo
->imo_membership
[i
] =
2393 in_addmulti(&mreq
->imr_multiaddr
, ifp
)) == NULL
) {
2397 ++imo
->imo_num_memberships
;
2403 * Drop membership of an IPv4 multicast.
2405 __private_extern__
int
2407 struct ip_moptions
*imo
,
2408 struct ip_mreq
*mreq
)
2411 struct ifnet
* ifp
= NULL
;
2414 if (!IN_MULTICAST(ntohl(mreq
->imr_multiaddr
.s_addr
))) {
2420 * If an interface address was specified, get a pointer
2421 * to its ifnet structure.
2423 if (mreq
->imr_interface
.s_addr
== INADDR_ANY
)
2426 ifp
= ip_multicast_if(&mreq
->imr_interface
, NULL
);
2428 error
= EADDRNOTAVAIL
;
2433 * Find the membership in the membership array.
2435 for (i
= 0; i
< imo
->imo_num_memberships
; ++i
) {
2437 imo
->imo_membership
[i
]->inm_ifp
== ifp
) &&
2438 imo
->imo_membership
[i
]->inm_addr
.s_addr
==
2439 mreq
->imr_multiaddr
.s_addr
)
2442 if (i
== imo
->imo_num_memberships
) {
2443 error
= EADDRNOTAVAIL
;
2447 * Give up the multicast address record to which the
2448 * membership points.
2450 in_delmulti(&imo
->imo_membership
[i
]);
2452 * Remove the gap in the membership array.
2454 for (++i
; i
< imo
->imo_num_memberships
; ++i
)
2455 imo
->imo_membership
[i
-1] = imo
->imo_membership
[i
];
2456 --imo
->imo_num_memberships
;
2462 * Return the IP multicast options in response to user getsockopt().
2465 ip_getmoptions(sopt
, imo
)
2466 struct sockopt
*sopt
;
2467 register struct ip_moptions
*imo
;
2469 struct in_addr addr
;
2470 struct in_ifaddr
*ia
;
2475 switch (sopt
->sopt_name
) {
2476 case IP_MULTICAST_VIF
:
2478 optval
= imo
->imo_multicast_vif
;
2481 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
2484 case IP_MULTICAST_IF
:
2485 if (imo
== NULL
|| imo
->imo_multicast_ifp
== NULL
)
2486 addr
.s_addr
= INADDR_ANY
;
2487 else if (imo
->imo_multicast_addr
.s_addr
) {
2488 /* return the value user has set */
2489 addr
= imo
->imo_multicast_addr
;
2491 IFP_TO_IA(imo
->imo_multicast_ifp
, ia
);
2492 addr
.s_addr
= (ia
== NULL
) ? INADDR_ANY
2493 : IA_SIN(ia
)->sin_addr
.s_addr
;
2495 error
= sooptcopyout(sopt
, &addr
, sizeof addr
);
2498 case IP_MULTICAST_TTL
:
2500 optval
= coptval
= IP_DEFAULT_MULTICAST_TTL
;
2502 optval
= coptval
= imo
->imo_multicast_ttl
;
2503 if (sopt
->sopt_valsize
== 1)
2504 error
= sooptcopyout(sopt
, &coptval
, 1);
2506 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
2509 case IP_MULTICAST_LOOP
:
2511 optval
= coptval
= IP_DEFAULT_MULTICAST_LOOP
;
2513 optval
= coptval
= imo
->imo_multicast_loop
;
2514 if (sopt
->sopt_valsize
== 1)
2515 error
= sooptcopyout(sopt
, &coptval
, 1);
2517 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
2521 error
= ENOPROTOOPT
;
2528 * Discard the IP multicast options.
2531 ip_freemoptions(imo
)
2532 register struct ip_moptions
*imo
;
2537 for (i
= 0; i
< imo
->imo_num_memberships
; ++i
)
2538 in_delmulti(&imo
->imo_membership
[i
]);
2539 FREE(imo
, M_IPMOPTS
);
2544 * Routine called from ip_output() to loop back a copy of an IP multicast
2545 * packet to the input queue of a specified interface. Note that this
2546 * calls the output routine of the loopback "driver", but with an interface
2547 * pointer that might NOT be a loopback interface -- evil, but easier than
2548 * replicating that code here.
2551 ip_mloopback(ifp
, m
, dst
, hlen
)
2553 register struct mbuf
*m
;
2554 register struct sockaddr_in
*dst
;
2557 register struct ip
*ip
;
2560 copym
= m_copy(m
, 0, M_COPYALL
);
2561 if (copym
!= NULL
&& (copym
->m_flags
& M_EXT
|| copym
->m_len
< hlen
))
2562 copym
= m_pullup(copym
, hlen
);
2563 if (copym
!= NULL
) {
2565 * We don't bother to fragment if the IP length is greater
2566 * than the interface's MTU. Can this possibly matter?
2568 ip
= mtod(copym
, struct ip
*);
2572 ip
->ip_sum
= in_cksum(copym
, hlen
);
2575 * It's not clear whether there are any lingering
2576 * reentrancy problems in other areas which might
2577 * be exposed by using ip_input directly (in
2578 * particular, everything which modifies the packet
2579 * in-place). Yet another option is using the
2580 * protosw directly to deliver the looped back
2581 * packet. For the moment, we'll err on the side
2582 * of safety by using if_simloop().
2585 if (dst
->sin_family
!= AF_INET
) {
2586 printf("ip_mloopback: bad address family %d\n",
2588 dst
->sin_family
= AF_INET
;
2594 * Mark checksum as valid or calculate checksum for loopback.
2596 * This is done this way because we have to embed the ifp of
2597 * the interface we will send the original copy of the packet
2598 * out on in the mbuf. ip_input will check if_hwassist of the
2599 * embedded ifp and ignore all csum_flags if if_hwassist is 0.
2600 * The UDP checksum has not been calculated yet.
2602 if (copym
->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA
) {
2603 if (IF_HWASSIST_CSUM_FLAGS(ifp
->if_hwassist
)) {
2604 copym
->m_pkthdr
.csum_flags
|=
2605 CSUM_DATA_VALID
| CSUM_PSEUDO_HDR
|
2606 CSUM_IP_CHECKED
| CSUM_IP_VALID
;
2607 copym
->m_pkthdr
.csum_data
= 0xffff;
2610 in_delayed_cksum(copym
);
2618 * We need to send all loopback traffic down to dlil in case
2619 * a filter has tapped-in.
2623 * Stuff the 'real' ifp into the pkthdr, to be used in matching
2624 * in ip_input(); we need the loopback ifp/dl_tag passed as args
2625 * to make the loopback driver compliant with the data link
2629 copym
->m_pkthdr
.rcvif
= ifp
;
2630 dlil_output(lo_ifp
, PF_INET
, copym
, 0, (struct sockaddr
*) dst
, 0);
2632 printf("Warning: ip_output call to dlil_find_dltag failed!\n");
2636 /* if_simloop(ifp, copym, (struct sockaddr *)dst, 0);*/