Deleted Added
full compact
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 ---