Skip to content

Instantly share code, notes, and snippets.

@gkoyuncu
Last active April 13, 2023 08:01
Show Gist options
  • Save gkoyuncu/f8aad43f66815dac7769 to your computer and use it in GitHub Desktop.
Save gkoyuncu/f8aad43f66815dac7769 to your computer and use it in GitHub Desktop.
pf DIOCNATLOOK example - taken from spamd/grey.c
/* Stolen from ftp-proxy */
int
server_lookup(struct sockaddr *client, struct sockaddr *proxy,
struct sockaddr *server)
{
if (client->sa_family == AF_INET)
return (server_lookup4(satosin(client), satosin(proxy),
satosin(server)));
if (client->sa_family == AF_INET6)
return (server_lookup6(satosin6(client), satosin6(proxy),
satosin6(server)));
errno = EPROTONOSUPPORT;
return (-1);
}
int
server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy,
struct sockaddr_in *server)
{
struct pfioc_natlook pnl;
#ifdef __FreeBSD__
if(!use_pf){
memset(server, 0, sizeof(struct sockaddr_in));
server->sin_family = AF_INET;
server->sin_len = sizeof(struct sockaddr_in);
memcpy(&server->sin_addr.s_addr, &proxy->sin_addr.s_addr, sizeof proxy->sin_addr.s_addr);
memcpy(&server->sin_port, &proxy->sin_port, sizeof proxy->sin_port);
return (0);
}
#endif
memset(&pnl, 0, sizeof pnl);
pnl.direction = PF_OUT;
pnl.af = AF_INET;
pnl.proto = IPPROTO_TCP;
memcpy(&pnl.saddr.v4, &client->sin_addr.s_addr, sizeof pnl.saddr.v4);
memcpy(&pnl.daddr.v4, &proxy->sin_addr.s_addr, sizeof pnl.daddr.v4);
pnl.sport = client->sin_port;
pnl.dport = proxy->sin_port;
if (ioctl(pfdev, DIOCNATLOOK, &pnl) == -1)
return (-1);
memset(server, 0, sizeof(struct sockaddr_in));
server->sin_len = sizeof(struct sockaddr_in);
server->sin_family = AF_INET;
memcpy(&server->sin_addr.s_addr, &pnl.rdaddr.v4,
sizeof server->sin_addr.s_addr);
server->sin_port = pnl.rdport;
return (0);
}
int
server_lookup6(struct sockaddr_in6 *client, struct sockaddr_in6 *proxy,
struct sockaddr_in6 *server)
{
struct pfioc_natlook pnl;
#ifdef __FreeBSD__
if(!use_pf){
memset(server, 0, sizeof(struct sockaddr_in6));
server->sin6_family = AF_INET6;
server->sin6_len = sizeof(struct sockaddr_in6);
memcpy(&server->sin6_addr.s6_addr, &proxy->sin6_addr.s6_addr, sizeof proxy->sin6_addr.s6_addr);
memcpy(&server->sin6_port, &proxy->sin6_port, sizeof proxy->sin6_port);
return (0);
}
#endif
memset(&pnl, 0, sizeof pnl);
pnl.direction = PF_OUT;
pnl.af = AF_INET6;
pnl.proto = IPPROTO_TCP;
memcpy(&pnl.saddr.v6, &client->sin6_addr.s6_addr, sizeof pnl.saddr.v6);
memcpy(&pnl.daddr.v6, &proxy->sin6_addr.s6_addr, sizeof pnl.daddr.v6);
pnl.sport = client->sin6_port;
pnl.dport = proxy->sin6_port;
if (ioctl(pfdev, DIOCNATLOOK, &pnl) == -1)
return (-1);
memset(server, 0, sizeof(struct sockaddr_in6));
server->sin6_len = sizeof(struct sockaddr_in6);
server->sin6_family = AF_INET6;
memcpy(&server->sin6_addr.s6_addr, &pnl.rdaddr.v6,
sizeof server->sin6_addr);
server->sin6_port = pnl.rdport;
return (0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment