ip_output.c (70dbc6cbfccdc5784be266c15d22b29f3d5fe216) ip_output.c (36e8826ffbfb16b1970dec46e3dd8487c014788a)
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

--- 76 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>
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

--- 76 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>
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
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
134ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
133ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
135 int flags, struct ip_moptions *imo, struct inpcb *inp)
136{
137 struct ip *ip;
138 struct ifnet *ifp = NULL; /* keep compiler happy */
134 int flags, struct ip_moptions *imo, struct inpcb *inp)
135{
136 struct ip *ip;
137 struct ifnet *ifp = NULL; /* keep compiler happy */
138 struct mbuf *m;
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;
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;
146 struct m_tag *dummytag; /* dummynet packet tag */
147 struct m_tag *mtag;
148 struct mbuf *m0; /* XXX */
149#ifdef IPSEC
150 struct secpolicy *sp = NULL;
151#endif
152#ifdef FAST_IPSEC
146#ifdef IPSEC
147 struct secpolicy *sp = NULL;
148#endif
149#ifdef FAST_IPSEC
150 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;
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;
162 args.next_hop = ip_claim_next_hop(m);
160 args.next_hop = NULL;
161 args.divert_rule = 0; /* divert cookie */
163
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 }
194 }
195 m = m0;
196
164 M_ASSERTPKTHDR(m);
165
166 if (ro == NULL) {
167 ro = &iproute;
168 bzero(ro, sizeof (*ro));
169 }
170
171 if (inp != NULL)
172 INP_LOCK_ASSERT(inp);
173
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
174 /*
175 * When packet comes from dummynet restore state from
176 * previous processing instead of the header. Yech!
177 *
178 * XXX add conditional compilation?
179 */
180 dummytag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
181 if (dummytag != NULL) {
182 struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
183
184 /*
185 * NB: the route in the tag is known to have a
186 * reference that must be free'd, but doing this
187 * before the storage is reclaimed is painful due
188 * to some of the contorted code in this routine.
189 * So instead unlink the tag from the mbuf so it
190 * doesn't get reclaimed and do the cleanup explicitly
191 * below. We should be able to do this automatically
192 * using a uma dtor method when m_tag's can be
193 * allocated from zones.
194 */
195 m_tag_unlink(m, dummytag);
196
197 args.rule = dt->rule;
198 ro = &dt->ro;
199 dst = dt->dn_dst;
200 ifp = dt->ifp;
201
207 if (args.rule != NULL) { /* dummynet already saw us */
202 ip = mtod(m, struct ip *);
203 hlen = ip->ip_hl << 2 ;
204 if (ro->ro_rt)
205 ia = ifatoia(ro->ro_rt->rt_ifa);
206 goto sendit;
207 }
208
209 if (opt) {

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

546 flags &= ~IP_ROUTETOIF;
547 ro = state.ro;
548 }
549 } else
550 ro = state.ro;
551 dst = (struct sockaddr_in *)state.dst;
552 if (error) {
553 /* mbuf is already reclaimed in ipsec4_output. */
208 ip = mtod(m, struct ip *);
209 hlen = ip->ip_hl << 2 ;
210 if (ro->ro_rt)
211 ia = ifatoia(ro->ro_rt->rt_ifa);
212 goto sendit;
213 }
214
215 if (opt) {

--- 336 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. */
554 m = NULL;
560 m0 = NULL;
555 switch (error) {
556 case EHOSTUNREACH:
557 case ENETUNREACH:
558 case EMSGSIZE:
559 case ENOBUFS:
560 case ENOMEM:
561 break;
562 default:

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

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

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

887 * of ours, we pretend to
888 * be the destination for this packet.
889 */
890 if (IA_SIN(ia)->sin_addr.s_addr ==
891 dst->sin_addr.s_addr)
892 break;
893 }
894 if (ia) { /* tell ip_input "dont filter" */
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" */
895 mtag = m_tag_get(PACKET_TAG_IPFORWARD,
896 sizeof(struct sockaddr_in *),
897 M_NOWAIT);
898 if (mtag == NULL) {
899 /* XXX statistic */
900 error = ENOBUFS; /* XXX */
901 goto bad;
902 }
903 *(struct sockaddr_in **)(mtag+1) =
904 args.next_hop;
905 m_tag_prepend(m, mtag);
899 struct m_hdr tag;
906
900
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;
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;
912 m->m_pkthdr.csum_data = 0xffff;
912 m0->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);
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);
918 /* XXX netisr_queue(NETISR_IP, m); */
919 ip_input(m);
918 ip_input((struct mbuf *)&tag);
920 goto done;
921 }
922 /*
923 * Some of the logic for this was
924 * nicked from above.
925 */
926 bcopy(dst, &ro_fwd->ro_dst, sizeof(*dst));
927

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

1068 if (error == 0)
1069 ipstat.ips_fragmented++;
1070
1071done:
1072 if (ro == &iproute && ro->ro_rt) {
1073 RTFREE(ro->ro_rt);
1074 ro->ro_rt = NULL;
1075 }
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 }
1076 if (dummytag) {
1077 struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
1078 if (dt->ro.ro_rt)
1079 RTFREE(dt->ro.ro_rt);
1080 m_tag_free(dummytag);
1081 }
1082#ifdef IPSEC
1083 if (sp != NULL) {
1084 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1085 printf("DP ip_output call free SP:%p\n", sp));
1086 key_freesp(sp);
1087 }
1088#endif
1089#ifdef FAST_IPSEC

--- 1166 unchanged lines hidden ---
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 ---