diff options
author | Sebastian Benoit <benno@cvs.openbsd.org> | 2012-10-21 13:06:04 +0000 |
---|---|---|
committer | Sebastian Benoit <benno@cvs.openbsd.org> | 2012-10-21 13:06:04 +0000 |
commit | 13f32dc0f32386032d455dd5fdf1dfd69753bc9b (patch) | |
tree | 7bc9068d988d2f743617f60fc94410b009530734 /sys/netinet6/ip6_divert.c | |
parent | 036204675e038878c1b3a43a17ff283b77e9d7ee (diff) |
Add the IP_DIVERTFL socket option on divert(4) sockets to control
which packets (as in direction) of the traffic will be diverted
through the divert socket.
ok claudio@, henning@
Diffstat (limited to 'sys/netinet6/ip6_divert.c')
-rw-r--r-- | sys/netinet6/ip6_divert.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/sys/netinet6/ip6_divert.c b/sys/netinet6/ip6_divert.c index 2894afafa77..fbc6d9551f5 100644 --- a/sys/netinet6/ip6_divert.c +++ b/sys/netinet6/ip6_divert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_divert.c,v 1.5 2010/07/03 04:44:51 guenther Exp $ */ +/* $OpenBSD: ip6_divert.c,v 1.6 2012/10/21 13:06:03 benno Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -135,7 +135,7 @@ divert6_output(struct mbuf *m, ...) return (error); } -void +int divert6_packet(struct mbuf *m, int dir) { struct inpcb *inp; @@ -143,19 +143,32 @@ divert6_packet(struct mbuf *m, int dir) struct sockaddr_in6 addr; struct pf_divert *pd; + inp = NULL; div6stat.divs_ipackets++; if (m->m_len < sizeof(struct ip6_hdr) && (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { div6stat.divs_errors++; - return; + return (0); } pd = pf_find_divert(m); if (pd == NULL) { div6stat.divs_errors++; m_freem(m); - return; + return (0); + } + + CIRCLEQ_FOREACH(inp, &divb6table.inpt_queue, inp_queue) { + if (inp->inp_lport != pd->port) + continue; + if (inp->inp_divertfl == 0) + break; + if (dir == PF_IN && !(inp->inp_divertfl & IPPROTO_DIVERT_RESP)) + return (-1); + if (dir == PF_OUT && !(inp->inp_divertfl & IPPROTO_DIVERT_INIT)) + return (-1); + break; } bzero(&addr, sizeof(addr)); @@ -176,25 +189,22 @@ divert6_packet(struct mbuf *m, int dir) } } - CIRCLEQ_FOREACH(inp, &divb6table.inpt_queue, inp_queue) { - if (inp->inp_lport != pd->port) - continue; - + if (inp != CIRCLEQ_END(&divb6table.inpt_queue)) { sa = inp->inp_socket; if (sbappendaddr(&sa->so_rcv, (struct sockaddr *)&addr, m, NULL) == 0) { div6stat.divs_fullsock++; m_freem(m); - return; + return (0); } else sorwakeup(inp->inp_socket); - break; } if (sa == NULL) { div6stat.divs_noport++; m_freem(m); } + return (0); } /*ARGSUSED*/ |