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