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