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