1.\" $OpenBSD: divert.4,v 1.16 2015/09/10 17:55:21 schwarze Exp $ 2.\" 3.\" Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> 4.\" Copyright (c) 2012-2014 Lawrence Teo <lteo@openbsd.org> 5.\" 6.\" Permission to use, copy, modify, and distribute this software for any 7.\" purpose with or without fee is hereby granted, provided that the above 8.\" copyright notice and this permission notice appear in all copies. 9.\" 10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17.\" 18.Dd $Mdocdate: September 10 2015 $ 19.Dt DIVERT 4 20.Os 21.Sh NAME 22.Nm divert 23.Nd kernel packet diversion mechanism 24.Sh SYNOPSIS 25.In sys/types.h 26.In sys/socket.h 27.In netinet/in.h 28.Ft int 29.Fn socket AF_INET SOCK_RAW IPPROTO_DIVERT 30.Ft int 31.Fn socket AF_INET6 SOCK_RAW IPPROTO_DIVERT 32.Sh DESCRIPTION 33Divert sockets are part of a mechanism completely integrated with 34.Xr pf 4 35that queues raw packets from the kernel stack to userspace applications, 36and vice versa. 37.Pp 38A divert socket must be bound to a divert port through 39.Xr bind 2 , 40which only the superuser can do. 41Divert ports have their own number space, completely separated from 42.Xr tcp 4 43and 44.Xr udp 4 . 45When 46.Xr pf 4 47processes a packet that matches a rule with the 48.Ar divert-packet 49parameter 50(see 51.Xr pf.conf 5 52for details) it is sent to the divert socket listening on the 53divert port specified in the rule. 54Note that 55.Ar divert-packet 56should not be confused with 57.Ar divert-to 58or 59.Ar divert-reply , 60which do not use divert sockets. 61.Xr pf 4 62reassembles TCP streams by default (if IP reassembly is not disabled) 63before sending them to the divert sockets. 64If there are no divert sockets listening, the packets are dropped. 65.Pp 66Packets can be read via 67.Xr read 2 , 68.Xr recv 2 , 69or 70.Xr recvfrom 2 71from the divert socket. 72The application that is processing the packets can then reinject them into the 73kernel. 74After being reinjected, inbound and outbound packets are treated differently. 75Inbound packets are added to the relevant input queue and a soft interrupt is 76scheduled to signal that a new packet is ready to be processed; outbound ones 77are processed directly by the relevant IPv4/IPv6 output function. 78Since the userspace application could have modified the packets, upon 79reinjection basic sanity checks are done to ensure that the packets are still 80valid. 81The packets' IPv4 and protocol checksums (TCP, UDP, ICMP, and ICMPv6) are also 82recalculated. 83.Pp 84Writing to a divert socket can be achieved using 85.Xr sendto 2 86and it will skip 87.Xr pf 4 88filters to avoid loops. 89A diverted packet that is not reinjected into the kernel stack is lost. 90.Pp 91Receive and send divert socket buffer space can be tuned through 92.Xr sysctl 8 . 93.Xr netstat 1 94shows information relevant to divert sockets. 95.Pp 96The IP_DIVERTFL socket option on the IPPROTO_IP level controls 97whether both inbound and outbound packets are diverted (the default) 98or only packets travelling in one direction. 99It cannot be reset once set. 100Valid values are 101.Dv IPPROTO_DIVERT_INIT 102for the direction of the initial packet of a flow, and 103.Dv IPPROTO_DIVERT_RESP 104for the direction of the response packets. 105.Sh EXAMPLES 106The following PF rule queues outbound IPv4 packets to TCP port 80, 107as well as the return traffic, on the em0 interface to divert port 700: 108.Bd -literal -offset indent 109pass out on em0 inet proto tcp to port 80 divert-packet port 700 110.Ed 111.Pp 112The following program reads packets on divert port 700 and reinjects them 113back into the kernel. 114This program does not perform any processing of the packets, 115apart from discarding invalid IP packets. 116.Bd -literal 117#include <sys/types.h> 118#include <sys/socket.h> 119#include <netinet/in.h> 120#include <netinet/ip.h> 121#include <netinet/tcp.h> 122#include <arpa/inet.h> 123#include <stdio.h> 124#include <string.h> 125#include <err.h> 126 127#define DIVERT_PORT 700 128 129int 130main(int argc, char *argv[]) 131{ 132 int fd, s; 133 struct sockaddr_in sin; 134 socklen_t sin_len; 135 136 fd = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT); 137 if (fd == -1) 138 err(1, "socket"); 139 140 memset(&sin, 0, sizeof(sin)); 141 sin.sin_family = AF_INET; 142 sin.sin_port = htons(DIVERT_PORT); 143 sin.sin_addr.s_addr = 0; 144 145 sin_len = sizeof(struct sockaddr_in); 146 147 s = bind(fd, (struct sockaddr *) &sin, sin_len); 148 if (s == -1) 149 err(1, "bind"); 150 151 for (;;) { 152 ssize_t n; 153 char packet[IP_MAXPACKET]; 154 struct ip *ip; 155 struct tcphdr *th; 156 int hlen; 157 char src[48], dst[48]; 158 159 memset(packet, 0, sizeof(packet)); 160 n = recvfrom(fd, packet, sizeof(packet), 0, 161 (struct sockaddr *) &sin, &sin_len); 162 if (n == -1) { 163 warn("recvfrom"); 164 continue; 165 } 166 if (n < sizeof(struct ip)) { 167 warnx("packet is too short"); 168 continue; 169 } 170 171 ip = (struct ip *) packet; 172 hlen = ip->ip_hl << 2; 173 if (hlen < sizeof(struct ip) || ntohs(ip->ip_len) < hlen || 174 n < ntohs(ip->ip_len)) { 175 warnx("invalid IPv4 packet"); 176 continue; 177 } 178 179 th = (struct tcphdr *) (packet + hlen); 180 181 if (inet_ntop(AF_INET, &ip->ip_src, src, 182 sizeof(src)) == NULL) 183 (void)strlcpy(src, "?", sizeof(src)); 184 185 if (inet_ntop(AF_INET, &ip->ip_dst, dst, 186 sizeof(dst)) == NULL) 187 (void)strlcpy(dst, "?", sizeof(dst)); 188 189 printf("%s:%u -> %s:%u\en", 190 src, 191 ntohs(th->th_sport), 192 dst, 193 ntohs(th->th_dport) 194 ); 195 196 n = sendto(fd, packet, n, 0, (struct sockaddr *) &sin, 197 sin_len); 198 if (n == -1) 199 warn("sendto"); 200 } 201 202 return 0; 203} 204.Ed 205.Sh SEE ALSO 206.Xr setsockopt 2 , 207.Xr socket 2 , 208.Xr ip 4 , 209.Xr pf.conf 5 210.Sh HISTORY 211The 212.Nm 213protocol first appeared in 214.Ox 4.7 . 215