ip_divert.c (125952) | ip_divert.c (126239) |
---|---|
1/* 2 * Copyright (c) 1982, 1986, 1988, 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 --- 16 unchanged lines hidden (view full) --- 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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 * | 1/* 2 * Copyright (c) 1982, 1986, 1988, 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 --- 16 unchanged lines hidden (view full) --- 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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 * $FreeBSD: head/sys/netinet/ip_divert.c 125952 2004-02-18 00:04:52Z mlaier $ | 33 * $FreeBSD: head/sys/netinet/ip_divert.c 126239 2004-02-25 19:55:29Z mlaier $ |
34 */ 35 36#include "opt_inet.h" 37#include "opt_ipfw.h" 38#include "opt_ipdivert.h" 39#include "opt_ipsec.h" 40#include "opt_mac.h" 41 --- 21 unchanged lines hidden (view full) --- 63#include <net/if.h> 64#include <net/route.h> 65 66#include <netinet/in.h> 67#include <netinet/in_pcb.h> 68#include <netinet/in_systm.h> 69#include <netinet/in_var.h> 70#include <netinet/ip.h> | 34 */ 35 36#include "opt_inet.h" 37#include "opt_ipfw.h" 38#include "opt_ipdivert.h" 39#include "opt_ipsec.h" 40#include "opt_mac.h" 41 --- 21 unchanged lines hidden (view full) --- 63#include <net/if.h> 64#include <net/route.h> 65 66#include <netinet/in.h> 67#include <netinet/in_pcb.h> 68#include <netinet/in_systm.h> 69#include <netinet/in_var.h> 70#include <netinet/ip.h> |
71#include <netinet/ip_divert.h> |
|
71#include <netinet/ip_var.h> 72 73/* 74 * Divert sockets 75 */ 76 77/* 78 * Allocate enough space to hold a full IP packet --- 66 unchanged lines hidden (view full) --- 145 146/* 147 * Divert a packet by passing it up to the divert socket at port 'port'. 148 * 149 * Setup generic address and protocol structures for div_input routine, 150 * then pass them along with mbuf chain. 151 */ 152void | 72#include <netinet/ip_var.h> 73 74/* 75 * Divert sockets 76 */ 77 78/* 79 * Allocate enough space to hold a full IP packet --- 66 unchanged lines hidden (view full) --- 146 147/* 148 * Divert a packet by passing it up to the divert socket at port 'port'. 149 * 150 * Setup generic address and protocol structures for div_input routine, 151 * then pass them along with mbuf chain. 152 */ 153void |
153divert_packet(struct mbuf *m, int incoming, int port, int rule) | 154divert_packet(struct mbuf *m, int incoming) |
154{ 155 struct ip *ip; 156 struct inpcb *inp; 157 struct socket *sa; 158 u_int16_t nport; 159 struct sockaddr_in divsrc; | 155{ 156 struct ip *ip; 157 struct inpcb *inp; 158 struct socket *sa; 159 u_int16_t nport; 160 struct sockaddr_in divsrc; |
161 struct m_tag *mtag; |
|
160 | 162 |
161 /* Sanity check */ 162 KASSERT(port != 0, ("%s: port=0", __func__)); 163 | 163 mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); 164 if (mtag == NULL) { 165 printf("%s: no divert tag\n", __func__); 166 m_freem(m); 167 return; 168 } |
164 /* Assure header */ 165 if (m->m_len < sizeof(struct ip) && 166 (m = m_pullup(m, sizeof(struct ip))) == 0) 167 return; 168 ip = mtod(m, struct ip *); 169 170 /* 171 * Record receive interface address, if any. 172 * But only for incoming packets. 173 */ 174 bzero(&divsrc, sizeof(divsrc)); 175 divsrc.sin_len = sizeof(divsrc); 176 divsrc.sin_family = AF_INET; | 169 /* Assure header */ 170 if (m->m_len < sizeof(struct ip) && 171 (m = m_pullup(m, sizeof(struct ip))) == 0) 172 return; 173 ip = mtod(m, struct ip *); 174 175 /* 176 * Record receive interface address, if any. 177 * But only for incoming packets. 178 */ 179 bzero(&divsrc, sizeof(divsrc)); 180 divsrc.sin_len = sizeof(divsrc); 181 divsrc.sin_family = AF_INET; |
177 divsrc.sin_port = rule; /* record matching rule */ | 182 divsrc.sin_port = divert_cookie(mtag); /* record matching rule */ |
178 if (incoming) { 179 struct ifaddr *ifa; 180 181 /* Sanity check */ 182 M_ASSERTPKTHDR(m); 183 184 /* Find IP address for receive interface */ 185 TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) { --- 43 unchanged lines hidden (view full) --- 229 * have to grab it regardless. This causes a LOR with 230 * the tcp lock, at least, and possibly others. For 231 * the moment we're ignoring this. Once sockets are 232 * locked this cruft can be removed. 233 */ 234 mtx_lock(&Giant); 235 /* Put packet on socket queue, if any */ 236 sa = NULL; | 183 if (incoming) { 184 struct ifaddr *ifa; 185 186 /* Sanity check */ 187 M_ASSERTPKTHDR(m); 188 189 /* Find IP address for receive interface */ 190 TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) { --- 43 unchanged lines hidden (view full) --- 234 * have to grab it regardless. This causes a LOR with 235 * the tcp lock, at least, and possibly others. For 236 * the moment we're ignoring this. Once sockets are 237 * locked this cruft can be removed. 238 */ 239 mtx_lock(&Giant); 240 /* Put packet on socket queue, if any */ 241 sa = NULL; |
237 nport = htons((u_int16_t)port); | 242 nport = htons((u_int16_t)divert_info(mtag)); |
238 INP_INFO_RLOCK(&divcbinfo); 239 LIST_FOREACH(inp, &divcb, inp_list) { 240 INP_LOCK(inp); 241 /* XXX why does only one socket match? */ 242 if (inp->inp_lport == nport) { 243 sa = inp->inp_socket; 244 if (sbappendaddr(&sa->so_rcv, 245 (struct sockaddr *)&divsrc, m, --- 22 unchanged lines hidden (view full) --- 268 * otherwise, send to ip_input() and mark as having been received on 269 * the interface with that address. 270 */ 271static int 272div_output(struct socket *so, struct mbuf *m, 273 struct sockaddr_in *sin, struct mbuf *control) 274{ 275 int error = 0; | 243 INP_INFO_RLOCK(&divcbinfo); 244 LIST_FOREACH(inp, &divcb, inp_list) { 245 INP_LOCK(inp); 246 /* XXX why does only one socket match? */ 247 if (inp->inp_lport == nport) { 248 sa = inp->inp_socket; 249 if (sbappendaddr(&sa->so_rcv, 250 (struct sockaddr *)&divsrc, m, --- 22 unchanged lines hidden (view full) --- 273 * otherwise, send to ip_input() and mark as having been received on 274 * the interface with that address. 275 */ 276static int 277div_output(struct socket *so, struct mbuf *m, 278 struct sockaddr_in *sin, struct mbuf *control) 279{ 280 int error = 0; |
276 struct m_hdr divert_tag; | |
277 | 281 |
278 /* 279 * Prepare the tag for divert info. Note that a packet 280 * with a 0 tag in mh_data is effectively untagged, 281 * so we could optimize that case. 282 */ 283 divert_tag.mh_type = MT_TAG; 284 divert_tag.mh_flags = PACKET_TAG_DIVERT; 285 divert_tag.mh_next = m; 286 divert_tag.mh_data = 0; /* the matching rule # */ 287 divert_tag.mh_nextpkt = NULL; 288 m->m_pkthdr.rcvif = NULL; /* XXX is it necessary ? */ | 282 KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null")); |
289 290#ifdef MAC 291 mac_create_mbuf_from_socket(so, m); 292#endif 293 294 if (control) 295 m_freem(control); /* XXX */ 296 297 /* Loopback avoidance and state recovery */ 298 if (sin) { | 283 284#ifdef MAC 285 mac_create_mbuf_from_socket(so, m); 286#endif 287 288 if (control) 289 m_freem(control); /* XXX */ 290 291 /* Loopback avoidance and state recovery */ 292 if (sin) { |
293 struct m_tag *mtag; 294 struct divert_tag *dt; |
|
299 int i; 300 | 295 int i; 296 |
301 divert_tag.mh_data = (caddr_t)(uintptr_t)sin->sin_port; | 297 mtag = m_tag_get(PACKET_TAG_DIVERT, 298 sizeof(struct divert_tag), M_NOWAIT); 299 if (mtag == NULL) { 300 error = ENOBUFS; 301 goto cantsend; 302 } 303 dt = (struct divert_tag *)(mtag+1); 304 dt->info = 0; 305 dt->cookie = sin->sin_port; 306 m_tag_prepend(m, mtag); 307 |
302 /* 303 * Find receive interface with the given name, stuffed 304 * (if it exists) in the sin_zero[] field. 305 * The name is user supplied data so don't trust its size 306 * or that it is zero terminated. 307 */ 308 for (i = 0; i < sizeof(sin->sin_zero) && sin->sin_zero[i]; i++) 309 ; --- 20 unchanged lines hidden (view full) --- 330 } else { 331 /* Convert fields to host order for ip_output() */ 332 ip->ip_len = ntohs(ip->ip_len); 333 ip->ip_off = ntohs(ip->ip_off); 334 335 /* Send packet to output processing */ 336 ipstat.ips_rawout++; /* XXX */ 337 | 308 /* 309 * Find receive interface with the given name, stuffed 310 * (if it exists) in the sin_zero[] field. 311 * The name is user supplied data so don't trust its size 312 * or that it is zero terminated. 313 */ 314 for (i = 0; i < sizeof(sin->sin_zero) && sin->sin_zero[i]; i++) 315 ; --- 20 unchanged lines hidden (view full) --- 336 } else { 337 /* Convert fields to host order for ip_output() */ 338 ip->ip_len = ntohs(ip->ip_len); 339 ip->ip_off = ntohs(ip->ip_off); 340 341 /* Send packet to output processing */ 342 ipstat.ips_rawout++; /* XXX */ 343 |
338 error = ip_output((struct mbuf *)&divert_tag, | 344 error = ip_output(m, |
339 inp->inp_options, NULL, 340 (so->so_options & SO_DONTROUTE) | 341 IP_ALLOWBROADCAST | IP_RAWOUTPUT, 342 inp->inp_moptions, NULL); 343 } 344 INP_UNLOCK(inp); 345 INP_INFO_WUNLOCK(&divcbinfo); 346 } else { --- 10 unchanged lines hidden (view full) --- 357 ifa = ifa_ifwithaddr((struct sockaddr *) sin); 358 if (ifa == NULL) { 359 error = EADDRNOTAVAIL; 360 goto cantsend; 361 } 362 m->m_pkthdr.rcvif = ifa->ifa_ifp; 363 } 364 /* Send packet to input processing */ | 345 inp->inp_options, NULL, 346 (so->so_options & SO_DONTROUTE) | 347 IP_ALLOWBROADCAST | IP_RAWOUTPUT, 348 inp->inp_moptions, NULL); 349 } 350 INP_UNLOCK(inp); 351 INP_INFO_WUNLOCK(&divcbinfo); 352 } else { --- 10 unchanged lines hidden (view full) --- 363 ifa = ifa_ifwithaddr((struct sockaddr *) sin); 364 if (ifa == NULL) { 365 error = EADDRNOTAVAIL; 366 goto cantsend; 367 } 368 m->m_pkthdr.rcvif = ifa->ifa_ifp; 369 } 370 /* Send packet to input processing */ |
365 ip_input((struct mbuf *)&divert_tag); | 371 ip_input(m); |
366 } 367 368 return error; 369 370cantsend: 371 m_freem(m); 372 return error; 373} 374 | 372 } 373 374 return error; 375 376cantsend: 377 m_freem(m); 378 return error; 379} 380 |
381/* 382 * Return a copy of the specified packet, but without 383 * the divert tag. This is used when packets are ``tee'd'' 384 * and we want the cloned copy to not have divert processing. 385 */ 386struct mbuf * 387divert_clone(struct mbuf *m) 388{ 389 struct mbuf *clone; 390 struct m_tag *mtag; 391 392 clone = m_dup(m, M_DONTWAIT); 393 if (clone != NULL) { 394 /* strip divert tag from copy */ 395 mtag = m_tag_find(clone, PACKET_TAG_DIVERT, NULL); 396 if (mtag != NULL) 397 m_tag_delete(clone, mtag); 398 } 399 return clone; 400} 401 |
|
375static int 376div_attach(struct socket *so, int proto, struct thread *td) 377{ 378 struct inpcb *inp; 379 int error; 380 381 INP_INFO_WLOCK(&divcbinfo); 382 inp = sotoinpcb(so); --- 271 unchanged lines hidden --- | 402static int 403div_attach(struct socket *so, int proto, struct thread *td) 404{ 405 struct inpcb *inp; 406 int error; 407 408 INP_INFO_WLOCK(&divcbinfo); 409 inp = sotoinpcb(so); --- 271 unchanged lines hidden --- |