Deleted Added
full compact
ip_output.c (125952) ip_output.c (126239)
1/*
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
1/*
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
34 * $FreeBSD: head/sys/netinet/ip_output.c 125952 2004-02-18 00:04:52Z mlaier $
34 * $FreeBSD: head/sys/netinet/ip_output.c 126239 2004-02-25 19:55:29Z mlaier $
35 */
36
37#include "opt_ipfw.h"
38#include "opt_ipdn.h"
39#include "opt_ipdivert.h"
40#include "opt_ipfilter.h"
41#include "opt_ipsec.h"
42#include "opt_mac.h"

--- 42 unchanged lines hidden (view full) ---

85
86#ifdef FAST_IPSEC
87#include <netipsec/ipsec.h>
88#include <netipsec/xform.h>
89#include <netipsec/key.h>
90#endif /*FAST_IPSEC*/
91
92#include <netinet/ip_fw.h>
35 */
36
37#include "opt_ipfw.h"
38#include "opt_ipdn.h"
39#include "opt_ipdivert.h"
40#include "opt_ipfilter.h"
41#include "opt_ipsec.h"
42#include "opt_mac.h"

--- 42 unchanged lines hidden (view full) ---

85
86#ifdef FAST_IPSEC
87#include <netipsec/ipsec.h>
88#include <netipsec/xform.h>
89#include <netipsec/key.h>
90#endif /*FAST_IPSEC*/
91
92#include <netinet/ip_fw.h>
93#include <netinet/ip_divert.h>
93#include <netinet/ip_dummynet.h>
94
95#define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\
96 x, (ntohl(a.s_addr)>>24)&0xFF,\
97 (ntohl(a.s_addr)>>16)&0xFF,\
98 (ntohl(a.s_addr)>>8)&0xFF,\
99 (ntohl(a.s_addr))&0xFF, y);
100

--- 24 unchanged lines hidden (view full) ---

125 * IP output. The packet in mbuf chain m contains a skeletal IP
126 * header (with len, off, ttl, proto, tos, src, dst).
127 * The mbuf chain containing the packet will be freed.
128 * The mbuf opt, if present, will not be freed.
129 * In the IP forwarding case, the packet will arrive with options already
130 * inserted, so must have a NULL opt pointer.
131 */
132int
94#include <netinet/ip_dummynet.h>
95
96#define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\
97 x, (ntohl(a.s_addr)>>24)&0xFF,\
98 (ntohl(a.s_addr)>>16)&0xFF,\
99 (ntohl(a.s_addr)>>8)&0xFF,\
100 (ntohl(a.s_addr))&0xFF, y);
101

--- 24 unchanged lines hidden (view full) ---

126 * IP output. The packet in mbuf chain m contains a skeletal IP
127 * header (with len, off, ttl, proto, tos, src, dst).
128 * The mbuf chain containing the packet will be freed.
129 * The mbuf opt, if present, will not be freed.
130 * In the IP forwarding case, the packet will arrive with options already
131 * inserted, so must have a NULL opt pointer.
132 */
133int
133ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
134ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
134 int flags, struct ip_moptions *imo, struct inpcb *inp)
135{
136 struct ip *ip;
137 struct ifnet *ifp = NULL; /* keep compiler happy */
135 int flags, struct ip_moptions *imo, struct inpcb *inp)
136{
137 struct ip *ip;
138 struct ifnet *ifp = NULL; /* keep compiler happy */
138 struct mbuf *m;
139 struct mbuf *m0;
139 int hlen = sizeof (struct ip);
140 int len, off, error = 0;
141 struct sockaddr_in *dst = NULL; /* keep compiler happy */
142 struct in_ifaddr *ia = NULL;
143 int isbroadcast, sw_csum;
144 struct in_addr pkt_dst;
145 struct route iproute;
140 int hlen = sizeof (struct ip);
141 int len, off, error = 0;
142 struct sockaddr_in *dst = NULL; /* keep compiler happy */
143 struct in_ifaddr *ia = NULL;
144 int isbroadcast, sw_csum;
145 struct in_addr pkt_dst;
146 struct route iproute;
147 struct m_tag *dummytag;
146#ifdef IPSEC
147 struct secpolicy *sp = NULL;
148#endif
149#ifdef FAST_IPSEC
150 struct m_tag *mtag;
151 struct secpolicy *sp = NULL;
152 struct tdb_ident *tdbi;
153 int s;
154#endif /* FAST_IPSEC */
155 struct ip_fw_args args;
156 int src_was_INADDR_ANY = 0; /* as the name says... */
157
158 args.eh = NULL;
159 args.rule = NULL;
148#ifdef IPSEC
149 struct secpolicy *sp = NULL;
150#endif
151#ifdef FAST_IPSEC
152 struct m_tag *mtag;
153 struct secpolicy *sp = NULL;
154 struct tdb_ident *tdbi;
155 int s;
156#endif /* FAST_IPSEC */
157 struct ip_fw_args args;
158 int src_was_INADDR_ANY = 0; /* as the name says... */
159
160 args.eh = NULL;
161 args.rule = NULL;
160 args.next_hop = NULL;
161 args.divert_rule = 0; /* divert cookie */
162
162
163 /* Grab info from MT_TAG mbufs prepended to the chain. */
164 for (; m0 && m0->m_type == MT_TAG; m0 = m0->m_next) {
165 switch(m0->_m_tag_id) {
166 default:
167 printf("ip_output: unrecognised MT_TAG tag %d\n",
168 m0->_m_tag_id);
169 break;
170
171 case PACKET_TAG_DUMMYNET:
172 /*
173 * the packet was already tagged, so part of the
174 * processing was already done, and we need to go down.
175 * Get parameters from the header.
176 */
177 args.rule = ((struct dn_pkt *)m0)->rule;
178 opt = NULL ;
179 ro = & ( ((struct dn_pkt *)m0)->ro ) ;
180 imo = NULL ;
181 dst = ((struct dn_pkt *)m0)->dn_dst ;
182 ifp = ((struct dn_pkt *)m0)->ifp ;
183 flags = ((struct dn_pkt *)m0)->flags ;
184 break;
185
186 case PACKET_TAG_DIVERT:
187 args.divert_rule = (intptr_t)m0->m_data & 0xffff;
188 break;
189
190 case PACKET_TAG_IPFORWARD:
191 args.next_hop = (struct sockaddr_in *)m0->m_data;
192 break;
193 }
163 M_ASSERTPKTHDR(m);
164
165 args.next_hop = ip_claim_next_hop(m);
166 dummytag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
167 if (dummytag != NULL) {
168 struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
169 /*
170 * Prevent lower layers from finding the tag
171 * Cleanup and free is done below
172 */
173 m_tag_unlink(m, dummytag);
174 /*
175 * the packet was already tagged, so part of the
176 * processing was already done, and we need to go down.
177 * Get parameters from the header.
178 */
179 args.rule = dt->rule;
180 ro = &(dt->ro);
181 dst = dt->dn_dst;
182 ifp = dt->ifp;
194 }
183 }
195 m = m0;
196
184
197 M_ASSERTPKTHDR(m);
198
199 if (ro == NULL) {
200 ro = &iproute;
201 bzero(ro, sizeof (*ro));
202 }
203
204 if (inp != NULL)
205 INP_LOCK_ASSERT(inp);
206

--- 345 unchanged lines hidden (view full) ---

552 flags &= ~IP_ROUTETOIF;
553 ro = state.ro;
554 }
555 } else
556 ro = state.ro;
557 dst = (struct sockaddr_in *)state.dst;
558 if (error) {
559 /* mbuf is already reclaimed in ipsec4_output. */
185 if (ro == NULL) {
186 ro = &iproute;
187 bzero(ro, sizeof (*ro));
188 }
189
190 if (inp != NULL)
191 INP_LOCK_ASSERT(inp);
192

--- 345 unchanged lines hidden (view full) ---

538 flags &= ~IP_ROUTETOIF;
539 ro = state.ro;
540 }
541 } else
542 ro = state.ro;
543 dst = (struct sockaddr_in *)state.dst;
544 if (error) {
545 /* mbuf is already reclaimed in ipsec4_output. */
560 m0 = NULL;
546 m = NULL;
561 switch (error) {
562 case EHOSTUNREACH:
563 case ENETUNREACH:
564 case EMSGSIZE:
565 case ENOBUFS:
566 case ENOMEM:
567 break;
568 default:

--- 223 unchanged lines hidden (view full) ---

792 args.flags = flags;
793
794 error = ip_dn_io_ptr(m, off & 0xffff, DN_TO_IP_OUT,
795 &args);
796 goto done;
797 }
798#ifdef IPDIVERT
799 if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
547 switch (error) {
548 case EHOSTUNREACH:
549 case ENETUNREACH:
550 case EMSGSIZE:
551 case ENOBUFS:
552 case ENOMEM:
553 break;
554 default:

--- 223 unchanged lines hidden (view full) ---

778 args.flags = flags;
779
780 error = ip_dn_io_ptr(m, off & 0xffff, DN_TO_IP_OUT,
781 &args);
782 goto done;
783 }
784#ifdef IPDIVERT
785 if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
800 struct mbuf *clone = NULL;
786 struct mbuf *clone;
801
802 /* Clone packet if we're doing a 'tee' */
803 if ((off & IP_FW_PORT_TEE_FLAG) != 0)
787
788 /* Clone packet if we're doing a 'tee' */
789 if ((off & IP_FW_PORT_TEE_FLAG) != 0)
804 clone = m_dup(m, M_DONTWAIT);
790 clone = divert_clone(m);
791 else
792 clone = NULL;
805
806 /*
807 * XXX
808 * delayed checksums are not currently compatible
809 * with divert sockets.
810 */
811 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
812 in_delayed_cksum(m);
813 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
814 }
815
816 /* Restore packet header fields to original values */
817 ip->ip_len = htons(ip->ip_len);
818 ip->ip_off = htons(ip->ip_off);
819
820 /* Deliver packet to divert input routine */
793
794 /*
795 * XXX
796 * delayed checksums are not currently compatible
797 * with divert sockets.
798 */
799 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
800 in_delayed_cksum(m);
801 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
802 }
803
804 /* Restore packet header fields to original values */
805 ip->ip_len = htons(ip->ip_len);
806 ip->ip_off = htons(ip->ip_off);
807
808 /* Deliver packet to divert input routine */
821 divert_packet(m, 0, off & 0xffff, args.divert_rule);
809 divert_packet(m, 0);
822
823 /* If 'tee', continue with original packet */
824 if (clone != NULL) {
825 m = clone;
826 ip = mtod(m, struct ip *);
827 goto pass;
828 }
829 goto done;

--- 61 unchanged lines hidden (view full) ---

891 * of ours, we pretend to
892 * be the destination for this packet.
893 */
894 if (IA_SIN(ia)->sin_addr.s_addr ==
895 dst->sin_addr.s_addr)
896 break;
897 }
898 if (ia) { /* tell ip_input "dont filter" */
810
811 /* If 'tee', continue with original packet */
812 if (clone != NULL) {
813 m = clone;
814 ip = mtod(m, struct ip *);
815 goto pass;
816 }
817 goto done;

--- 61 unchanged lines hidden (view full) ---

879 * of ours, we pretend to
880 * be the destination for this packet.
881 */
882 if (IA_SIN(ia)->sin_addr.s_addr ==
883 dst->sin_addr.s_addr)
884 break;
885 }
886 if (ia) { /* tell ip_input "dont filter" */
899 struct m_hdr tag;
887 struct m_tag *mtag = m_tag_get(
888 PACKET_TAG_IPFORWARD,
889 sizeof(struct sockaddr_in *), M_NOWAIT);
890 if (mtag == NULL) {
891 error = ENOBUFS;
892 goto bad;
893 }
894 *(struct sockaddr_in **)(mtag+1) =
895 args.next_hop;
896 m_tag_prepend(m, mtag);
900
897
901 tag.mh_type = MT_TAG;
902 tag.mh_flags = PACKET_TAG_IPFORWARD;
903 tag.mh_data = (caddr_t)args.next_hop;
904 tag.mh_next = m;
905 tag.mh_nextpkt = NULL;
906
907 if (m->m_pkthdr.rcvif == NULL)
908 m->m_pkthdr.rcvif = ifunit("lo0");
909 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
910 m->m_pkthdr.csum_flags |=
911 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
898 if (m->m_pkthdr.rcvif == NULL)
899 m->m_pkthdr.rcvif = ifunit("lo0");
900 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
901 m->m_pkthdr.csum_flags |=
902 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
912 m0->m_pkthdr.csum_data = 0xffff;
903 m->m_pkthdr.csum_data = 0xffff;
913 }
914 m->m_pkthdr.csum_flags |=
915 CSUM_IP_CHECKED | CSUM_IP_VALID;
916 ip->ip_len = htons(ip->ip_len);
917 ip->ip_off = htons(ip->ip_off);
904 }
905 m->m_pkthdr.csum_flags |=
906 CSUM_IP_CHECKED | CSUM_IP_VALID;
907 ip->ip_len = htons(ip->ip_len);
908 ip->ip_off = htons(ip->ip_off);
918 ip_input((struct mbuf *)&tag);
909 ip_input(m);
919 goto done;
920 }
921 /*
922 * Some of the logic for this was
923 * nicked from above.
924 */
925 bcopy(dst, &ro_fwd->ro_dst, sizeof(*dst));
926

--- 140 unchanged lines hidden (view full) ---

1067 if (error == 0)
1068 ipstat.ips_fragmented++;
1069
1070done:
1071 if (ro == &iproute && ro->ro_rt) {
1072 RTFREE(ro->ro_rt);
1073 ro->ro_rt = NULL;
1074 }
910 goto done;
911 }
912 /*
913 * Some of the logic for this was
914 * nicked from above.
915 */
916 bcopy(dst, &ro_fwd->ro_dst, sizeof(*dst));
917

--- 140 unchanged lines hidden (view full) ---

1058 if (error == 0)
1059 ipstat.ips_fragmented++;
1060
1061done:
1062 if (ro == &iproute && ro->ro_rt) {
1063 RTFREE(ro->ro_rt);
1064 ro->ro_rt = NULL;
1065 }
1066 if (dummytag) {
1067 struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
1068 if (dt->ro.ro_rt)
1069 RTFREE(dt->ro.ro_rt);
1070 m_tag_free(dummytag);
1071 }
1075#ifdef IPSEC
1076 if (sp != NULL) {
1077 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1078 printf("DP ip_output call free SP:%p\n", sp));
1079 key_freesp(sp);
1080 }
1081#endif
1082#ifdef FAST_IPSEC

--- 1166 unchanged lines hidden ---
1072#ifdef IPSEC
1073 if (sp != NULL) {
1074 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1075 printf("DP ip_output call free SP:%p\n", sp));
1076 key_freesp(sp);
1077 }
1078#endif
1079#ifdef FAST_IPSEC

--- 1166 unchanged lines hidden ---