ip_output.c (57855) | ip_output.c (58698) |
---|---|
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 57855 2000-03-09 14:57:16Z shin $ | 34 * $FreeBSD: head/sys/netinet/ip_output.c 58698 2000-03-27 19:14:27Z jlemon $ |
35 */ 36 37#define _IP_VHL 38 39#include "opt_ipfw.h" 40#include "opt_ipdn.h" 41#include "opt_ipdivert.h" 42#include "opt_ipfilter.h" --- 48 unchanged lines hidden (view full) --- 91#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\ 92 (ntohl(a.s_addr)>>16)&0xFF,\ 93 (ntohl(a.s_addr)>>8)&0xFF,\ 94 (ntohl(a.s_addr))&0xFF); 95#endif 96 97u_short ip_id; 98 | 35 */ 36 37#define _IP_VHL 38 39#include "opt_ipfw.h" 40#include "opt_ipdn.h" 41#include "opt_ipdivert.h" 42#include "opt_ipfilter.h" --- 48 unchanged lines hidden (view full) --- 91#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\ 92 (ntohl(a.s_addr)>>16)&0xFF,\ 93 (ntohl(a.s_addr)>>8)&0xFF,\ 94 (ntohl(a.s_addr))&0xFF); 95#endif 96 97u_short ip_id; 98 |
99static void in_delayed_cksum(struct mbuf *m); |
|
99static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); 100static void ip_mloopback 101 __P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int)); 102static int ip_getmoptions 103 __P((struct sockopt *, struct ip_moptions *)); 104static int ip_pcbopts __P((int, struct mbuf **, struct mbuf *)); 105static int ip_setmoptions 106 __P((struct sockopt *, struct ip_moptions **)); --- 20 unchanged lines hidden (view full) --- 127{ 128 struct ip *ip, *mhip; 129 struct ifnet *ifp; 130 struct mbuf *m = m0; 131 int hlen = sizeof (struct ip); 132 int len, off, error = 0; 133 struct sockaddr_in *dst; 134 struct in_ifaddr *ia; | 100static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); 101static void ip_mloopback 102 __P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int)); 103static int ip_getmoptions 104 __P((struct sockopt *, struct ip_moptions *)); 105static int ip_pcbopts __P((int, struct mbuf **, struct mbuf *)); 106static int ip_setmoptions 107 __P((struct sockopt *, struct ip_moptions **)); --- 20 unchanged lines hidden (view full) --- 128{ 129 struct ip *ip, *mhip; 130 struct ifnet *ifp; 131 struct mbuf *m = m0; 132 int hlen = sizeof (struct ip); 133 int len, off, error = 0; 134 struct sockaddr_in *dst; 135 struct in_ifaddr *ia; |
135 int isbroadcast; | 136 int isbroadcast, sw_csum; |
136#ifdef IPSEC 137 struct route iproute; 138 struct socket *so = NULL; 139 struct secpolicy *sp = NULL; 140#endif 141 u_int16_t divert_cookie; /* firewall cookie */ 142#ifdef IPFIREWALL_FORWARD 143 int fwd_rewrite_src = 0; --- 543 unchanged lines hidden (view full) --- 687 state.m = m; 688 if (flags & IP_ROUTETOIF) { 689 state.ro = &iproute; 690 bzero(&iproute, sizeof(iproute)); 691 } else 692 state.ro = ro; 693 state.dst = (struct sockaddr *)dst; 694 | 137#ifdef IPSEC 138 struct route iproute; 139 struct socket *so = NULL; 140 struct secpolicy *sp = NULL; 141#endif 142 u_int16_t divert_cookie; /* firewall cookie */ 143#ifdef IPFIREWALL_FORWARD 144 int fwd_rewrite_src = 0; --- 543 unchanged lines hidden (view full) --- 688 state.m = m; 689 if (flags & IP_ROUTETOIF) { 690 state.ro = &iproute; 691 bzero(&iproute, sizeof(iproute)); 692 } else 693 state.ro = ro; 694 state.dst = (struct sockaddr *)dst; 695 |
696 /* 697 * XXX 698 * delayed checksums are not currently compatible with IPsec 699 */ 700 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 701 in_delayed_cksum(m); 702 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 703 } 704 |
|
695 error = ipsec4_output(&state, sp, flags); 696 697 m = state.m; 698 if (flags & IP_ROUTETOIF) { 699 /* 700 * if we have tunnel mode SA, we may need to ignore 701 * IP_ROUTETOIF. 702 */ --- 46 unchanged lines hidden (view full) --- 749 } 750 751 /* make it flipped, again. */ 752 ip->ip_len = ntohs((u_short)ip->ip_len); 753 ip->ip_off = ntohs((u_short)ip->ip_off); 754skip_ipsec: 755#endif /*IPSEC*/ 756 | 705 error = ipsec4_output(&state, sp, flags); 706 707 m = state.m; 708 if (flags & IP_ROUTETOIF) { 709 /* 710 * if we have tunnel mode SA, we may need to ignore 711 * IP_ROUTETOIF. 712 */ --- 46 unchanged lines hidden (view full) --- 759 } 760 761 /* make it flipped, again. */ 762 ip->ip_len = ntohs((u_short)ip->ip_len); 763 ip->ip_off = ntohs((u_short)ip->ip_off); 764skip_ipsec: 765#endif /*IPSEC*/ 766 |
767 sw_csum = m->m_pkthdr.csum_flags | CSUM_IP; 768 m->m_pkthdr.csum_flags = sw_csum & ifp->if_hwassist; 769 sw_csum &= ~ifp->if_hwassist; 770 if (sw_csum & CSUM_DELAY_DATA) { 771 in_delayed_cksum(m); 772 sw_csum &= ~CSUM_DELAY_DATA; 773 } 774 |
|
757 /* | 775 /* |
758 * If small enough for interface, can just send directly. | 776 * If small enough for interface, or the interface will take 777 * care of the fragmentation for us, can just send directly. |
759 */ | 778 */ |
760 if ((u_short)ip->ip_len <= ifp->if_mtu) { | 779 if ((u_short)ip->ip_len <= ifp->if_mtu || 780 ifp->if_hwassist & CSUM_FRAGMENT) { |
761 ip->ip_len = htons((u_short)ip->ip_len); 762 ip->ip_off = htons((u_short)ip->ip_off); 763 ip->ip_sum = 0; | 781 ip->ip_len = htons((u_short)ip->ip_len); 782 ip->ip_off = htons((u_short)ip->ip_off); 783 ip->ip_sum = 0; |
764 if (ip->ip_vhl == IP_VHL_BORING) { 765 ip->ip_sum = in_cksum_hdr(ip); 766 } else { 767 ip->ip_sum = in_cksum(m, hlen); | 784 if (sw_csum & CSUM_DELAY_IP) { 785 if (ip->ip_vhl == IP_VHL_BORING) { 786 ip->ip_sum = in_cksum_hdr(ip); 787 } else { 788 ip->ip_sum = in_cksum(m, hlen); 789 } |
768 } 769 error = (*ifp->if_output)(ifp, m, 770 (struct sockaddr *)dst, ro->ro_rt); 771 goto done; 772 } 773 /* 774 * Too large for interface; fragment if possible. 775 * Must be able to put at least 8 bytes per fragment. --- 16 unchanged lines hidden (view full) --- 792 goto bad; 793 } 794 len = (ifp->if_mtu - hlen) &~ 7; 795 if (len < 8) { 796 error = EMSGSIZE; 797 goto bad; 798 } 799 | 790 } 791 error = (*ifp->if_output)(ifp, m, 792 (struct sockaddr *)dst, ro->ro_rt); 793 goto done; 794 } 795 /* 796 * Too large for interface; fragment if possible. 797 * Must be able to put at least 8 bytes per fragment. --- 16 unchanged lines hidden (view full) --- 814 goto bad; 815 } 816 len = (ifp->if_mtu - hlen) &~ 7; 817 if (len < 8) { 818 error = EMSGSIZE; 819 goto bad; 820 } 821 |
822 /* 823 * if the interface will not calculate checksums on 824 * fragmented packets, then do it here. 825 */ 826 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA && 827 (ifp->if_hwassist & CSUM_IP_FRAGS) == 0) { 828 in_delayed_cksum(m); 829 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 830 } 831 |
|
800 { 801 int mhlen, firstlen = len; 802 struct mbuf **mnext = &m->m_nextpkt; | 832 { 833 int mhlen, firstlen = len; 834 struct mbuf **mnext = &m->m_nextpkt; |
835 int nfrags = 1; |
|
803 804 /* 805 * Loop through length of segment after first fragment, 806 * make new header and copy data of each part and link onto chain. 807 */ 808 m0 = m; 809 mhlen = sizeof (struct ip); 810 for (off = hlen + len; off < (u_short)ip->ip_len; off += len) { 811 MGETHDR(m, M_DONTWAIT, MT_HEADER); 812 if (m == 0) { 813 error = ENOBUFS; 814 ipstat.ips_odropped++; 815 goto sendorfree; 816 } | 836 837 /* 838 * Loop through length of segment after first fragment, 839 * make new header and copy data of each part and link onto chain. 840 */ 841 m0 = m; 842 mhlen = sizeof (struct ip); 843 for (off = hlen + len; off < (u_short)ip->ip_len; off += len) { 844 MGETHDR(m, M_DONTWAIT, MT_HEADER); 845 if (m == 0) { 846 error = ENOBUFS; 847 ipstat.ips_odropped++; 848 goto sendorfree; 849 } |
817 m->m_flags |= (m0->m_flags & M_MCAST); | 850 m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG; |
818 m->m_data += max_linkhdr; 819 mhip = mtod(m, struct ip *); 820 *mhip = *ip; 821 if (hlen > sizeof (struct ip)) { 822 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 823 mhip->ip_vhl = IP_MAKE_VHL(IPVERSION, mhlen >> 2); 824 } 825 m->m_len = mhlen; --- 9 unchanged lines hidden (view full) --- 835 if (m->m_next == 0) { 836 (void) m_free(m); 837 error = ENOBUFS; /* ??? */ 838 ipstat.ips_odropped++; 839 goto sendorfree; 840 } 841 m->m_pkthdr.len = mhlen + len; 842 m->m_pkthdr.rcvif = (struct ifnet *)0; | 851 m->m_data += max_linkhdr; 852 mhip = mtod(m, struct ip *); 853 *mhip = *ip; 854 if (hlen > sizeof (struct ip)) { 855 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 856 mhip->ip_vhl = IP_MAKE_VHL(IPVERSION, mhlen >> 2); 857 } 858 m->m_len = mhlen; --- 9 unchanged lines hidden (view full) --- 868 if (m->m_next == 0) { 869 (void) m_free(m); 870 error = ENOBUFS; /* ??? */ 871 ipstat.ips_odropped++; 872 goto sendorfree; 873 } 874 m->m_pkthdr.len = mhlen + len; 875 m->m_pkthdr.rcvif = (struct ifnet *)0; |
876 m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags; |
|
843 mhip->ip_off = htons((u_short)mhip->ip_off); 844 mhip->ip_sum = 0; | 877 mhip->ip_off = htons((u_short)mhip->ip_off); 878 mhip->ip_sum = 0; |
845 if (mhip->ip_vhl == IP_VHL_BORING) { 846 mhip->ip_sum = in_cksum_hdr(mhip); 847 } else { 848 mhip->ip_sum = in_cksum(m, mhlen); | 879 if (sw_csum & CSUM_DELAY_IP) { 880 if (mhip->ip_vhl == IP_VHL_BORING) { 881 mhip->ip_sum = in_cksum_hdr(mhip); 882 } else { 883 mhip->ip_sum = in_cksum(m, mhlen); 884 } |
849 } 850 *mnext = m; 851 mnext = &m->m_nextpkt; | 885 } 886 *mnext = m; 887 mnext = &m->m_nextpkt; |
852 ipstat.ips_ofragments++; | 888 nfrags++; |
853 } | 889 } |
890 ipstat.ips_ofragments += nfrags; 891 892 /* set first/last markers for fragment chain */ 893 m->m_flags |= M_LASTFRAG; 894 m0->m_flags |= M_FIRSTFRAG | M_FRAG; 895 m0->m_pkthdr.csum_data = nfrags; 896 |
|
854 /* 855 * Update first fragment by trimming what's been copied out 856 * and updating header, then send each fragment (in order). 857 */ 858 m = m0; 859 m_adj(m, hlen + firstlen - (u_short)ip->ip_len); 860 m->m_pkthdr.len = hlen + firstlen; 861 ip->ip_len = htons((u_short)m->m_pkthdr.len); 862 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); 863 ip->ip_sum = 0; | 897 /* 898 * Update first fragment by trimming what's been copied out 899 * and updating header, then send each fragment (in order). 900 */ 901 m = m0; 902 m_adj(m, hlen + firstlen - (u_short)ip->ip_len); 903 m->m_pkthdr.len = hlen + firstlen; 904 ip->ip_len = htons((u_short)m->m_pkthdr.len); 905 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); 906 ip->ip_sum = 0; |
864 if (ip->ip_vhl == IP_VHL_BORING) { 865 ip->ip_sum = in_cksum_hdr(ip); 866 } else { 867 ip->ip_sum = in_cksum(m, hlen); | 907 if (sw_csum & CSUM_DELAY_IP) { 908 if (ip->ip_vhl == IP_VHL_BORING) { 909 ip->ip_sum = in_cksum_hdr(ip); 910 } else { 911 ip->ip_sum = in_cksum(m, hlen); 912 } |
868 } 869sendorfree: 870 for (m = m0; m; m = m0) { 871 m0 = m->m_nextpkt; 872 m->m_nextpkt = 0; 873 if (error == 0) 874 error = (*ifp->if_output)(ifp, m, 875 (struct sockaddr *)dst, ro->ro_rt); --- 17 unchanged lines hidden (view full) --- 893 } 894#endif /* IPSEC */ 895 return (error); 896bad: 897 m_freem(m0); 898 goto done; 899} 900 | 913 } 914sendorfree: 915 for (m = m0; m; m = m0) { 916 m0 = m->m_nextpkt; 917 m->m_nextpkt = 0; 918 if (error == 0) 919 error = (*ifp->if_output)(ifp, m, 920 (struct sockaddr *)dst, ro->ro_rt); --- 17 unchanged lines hidden (view full) --- 938 } 939#endif /* IPSEC */ 940 return (error); 941bad: 942 m_freem(m0); 943 goto done; 944} 945 |
946static void 947in_delayed_cksum(struct mbuf *m) 948{ 949 struct ip *ip; 950 u_short csum, offset; 951 952 ip = mtod(m, struct ip *); 953 offset = IP_VHL_HL(ip->ip_vhl) << 2 ; 954 csum = in_cksum_skip(m, ip->ip_len, offset); 955 offset += m->m_pkthdr.csum_data; /* checksum offset */ 956 957 if (offset + sizeof(u_short) > m->m_len) { 958 printf("delayed m_pullup, m->len: %d off: %d p: %d\n", 959 m->m_len, offset, ip->ip_p); 960 /* 961 * XXX 962 * this shouldn't happen, but if it does, the 963 * correct behavior may be to insert the checksum 964 * in the existing chain instead of rearranging it. 965 */ 966 m = m_pullup(m, offset + sizeof(u_short)); 967 } 968 *(u_short *)(m->m_data + offset) = csum; 969} 970 |
|
901/* 902 * Insert IP options into preformed packet. 903 * Adjust IP destination as required for IP source routing, 904 * as indicated by a non-zero in_addr at the start of the options. 905 * 906 * XXX This routine assumes that the packet has no options in place. 907 */ 908static struct mbuf * --- 886 unchanged lines hidden --- | 971/* 972 * Insert IP options into preformed packet. 973 * Adjust IP destination as required for IP source routing, 974 * as indicated by a non-zero in_addr at the start of the options. 975 * 976 * XXX This routine assumes that the packet has no options in place. 977 */ 978static struct mbuf * --- 886 unchanged lines hidden --- |