Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf.c
Show First 20 Lines • Show All 237 Lines • ▼ Show 20 Lines | static void pf_change_ap(struct mbuf *, struct pf_addr *, u_int16_t *, | ||||
u_int16_t *, u_int16_t *, struct pf_addr *, | u_int16_t *, u_int16_t *, struct pf_addr *, | ||||
u_int16_t, u_int8_t, sa_family_t); | u_int16_t, u_int8_t, sa_family_t); | ||||
static int pf_modulate_sack(struct mbuf *, int, struct pf_pdesc *, | static int pf_modulate_sack(struct mbuf *, int, struct pf_pdesc *, | ||||
struct tcphdr *, struct pf_state_peer *); | struct tcphdr *, struct pf_state_peer *); | ||||
static void pf_change_icmp(struct pf_addr *, u_int16_t *, | static void pf_change_icmp(struct pf_addr *, u_int16_t *, | ||||
struct pf_addr *, struct pf_addr *, u_int16_t, | struct pf_addr *, struct pf_addr *, u_int16_t, | ||||
u_int16_t *, u_int16_t *, u_int16_t *, | u_int16_t *, u_int16_t *, u_int16_t *, | ||||
u_int16_t *, u_int8_t, sa_family_t); | u_int16_t *, u_int8_t, sa_family_t); | ||||
static void pf_send_tcp(const struct pf_krule *, sa_family_t, | |||||
const struct pf_addr *, const struct pf_addr *, | |||||
u_int16_t, u_int16_t, u_int32_t, u_int32_t, | |||||
u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, | |||||
u_int16_t); | |||||
static void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t, | static void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t, | ||||
sa_family_t, struct pf_krule *); | sa_family_t, struct pf_krule *); | ||||
static void pf_detach_state(struct pf_kstate *); | static void pf_detach_state(struct pf_kstate *); | ||||
static int pf_state_key_attach(struct pf_state_key *, | static int pf_state_key_attach(struct pf_state_key *, | ||||
struct pf_state_key *, struct pf_kstate *); | struct pf_state_key *, struct pf_kstate *); | ||||
static void pf_state_key_detach(struct pf_kstate *, int); | static void pf_state_key_detach(struct pf_kstate *, int); | ||||
static int pf_state_key_ctor(void *, int, void *, int); | static int pf_state_key_ctor(void *, int, void *, int); | ||||
static u_int32_t pf_tcp_iss(struct pf_pdesc *); | static u_int32_t pf_tcp_iss(struct pf_pdesc *); | ||||
Show All 27 Lines | |||||
static int pf_test_state_udp(struct pf_kstate **, int, | static int pf_test_state_udp(struct pf_kstate **, int, | ||||
struct pfi_kkif *, struct mbuf *, int, | struct pfi_kkif *, struct mbuf *, int, | ||||
void *, struct pf_pdesc *); | void *, struct pf_pdesc *); | ||||
static int pf_test_state_icmp(struct pf_kstate **, int, | static int pf_test_state_icmp(struct pf_kstate **, int, | ||||
struct pfi_kkif *, struct mbuf *, int, | struct pfi_kkif *, struct mbuf *, int, | ||||
void *, struct pf_pdesc *, u_short *); | void *, struct pf_pdesc *, u_short *); | ||||
static int pf_test_state_other(struct pf_kstate **, int, | static int pf_test_state_other(struct pf_kstate **, int, | ||||
struct pfi_kkif *, struct mbuf *, struct pf_pdesc *); | struct pfi_kkif *, struct mbuf *, struct pf_pdesc *); | ||||
static u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t, | |||||
sa_family_t); | |||||
static u_int16_t pf_get_mss(struct mbuf *, int, u_int16_t, | |||||
sa_family_t); | |||||
static u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, | static u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, | ||||
int, u_int16_t); | int, u_int16_t); | ||||
static int pf_check_proto_cksum(struct mbuf *, int, int, | static int pf_check_proto_cksum(struct mbuf *, int, int, | ||||
u_int8_t, sa_family_t); | u_int8_t, sa_family_t); | ||||
static void pf_print_state_parts(struct pf_kstate *, | static void pf_print_state_parts(struct pf_kstate *, | ||||
struct pf_state_key *, struct pf_state_key *); | struct pf_state_key *, struct pf_state_key *); | ||||
static int pf_addr_wrap_neq(struct pf_addr_wrap *, | static int pf_addr_wrap_neq(struct pf_addr_wrap *, | ||||
struct pf_addr_wrap *); | struct pf_addr_wrap *); | ||||
▲ Show 20 Lines • Show All 2,142 Lines • ▼ Show 20 Lines | while (hlen >= TCPOLEN_SACKLEN) { | ||||
} | } | ||||
} | } | ||||
if (copyback) | if (copyback) | ||||
m_copyback(m, off + sizeof(*th), thoptlen, (caddr_t)opts); | m_copyback(m, off + sizeof(*th), thoptlen, (caddr_t)opts); | ||||
return (copyback); | return (copyback); | ||||
} | } | ||||
static void | struct mbuf * | ||||
pf_send_tcp(const struct pf_krule *r, sa_family_t af, | pf_build_tcp(const struct pf_krule *r, sa_family_t af, | ||||
const struct pf_addr *saddr, const struct pf_addr *daddr, | const struct pf_addr *saddr, const struct pf_addr *daddr, | ||||
u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, | u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, | ||||
u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag, | u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag, | ||||
u_int16_t rtag) | u_int16_t rtag) | ||||
{ | { | ||||
struct pf_send_entry *pfse; | |||||
struct mbuf *m; | struct mbuf *m; | ||||
int len, tlen; | int len, tlen; | ||||
#ifdef INET | #ifdef INET | ||||
struct ip *h = NULL; | struct ip *h = NULL; | ||||
#endif /* INET */ | #endif /* INET */ | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct ip6_hdr *h6 = NULL; | struct ip6_hdr *h6 = NULL; | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
Show All 19 Lines | #ifdef INET6 | ||||
case AF_INET6: | case AF_INET6: | ||||
len = sizeof(struct ip6_hdr) + tlen; | len = sizeof(struct ip6_hdr) + tlen; | ||||
break; | break; | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
default: | default: | ||||
panic("%s: unsupported af %d", __func__, af); | panic("%s: unsupported af %d", __func__, af); | ||||
} | } | ||||
/* Allocate outgoing queue entry, mbuf and mbuf tag. */ | |||||
pfse = malloc(sizeof(*pfse), M_PFTEMP, M_NOWAIT); | |||||
if (pfse == NULL) | |||||
return; | |||||
m = m_gethdr(M_NOWAIT, MT_DATA); | m = m_gethdr(M_NOWAIT, MT_DATA); | ||||
if (m == NULL) { | if (m == NULL) | ||||
free(pfse, M_PFTEMP); | return (NULL); | ||||
return; | |||||
} | |||||
#ifdef MAC | #ifdef MAC | ||||
mac_netinet_firewall_send(m); | mac_netinet_firewall_send(m); | ||||
#endif | #endif | ||||
if ((pf_mtag = pf_get_mtag(m)) == NULL) { | if ((pf_mtag = pf_get_mtag(m)) == NULL) { | ||||
free(pfse, M_PFTEMP); | |||||
m_freem(m); | m_freem(m); | ||||
return; | return (NULL); | ||||
} | } | ||||
if (tag) | if (tag) | ||||
m->m_flags |= M_SKIP_FIREWALL; | m->m_flags |= M_SKIP_FIREWALL; | ||||
pf_mtag->tag = rtag; | pf_mtag->tag = rtag; | ||||
if (r != NULL && r->rtableid >= 0) | if (r != NULL && r->rtableid >= 0) | ||||
M_SETFIB(m, r->rtableid); | M_SETFIB(m, r->rtableid); | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | case AF_INET: | ||||
/* Finish the IP header */ | /* Finish the IP header */ | ||||
h->ip_v = 4; | h->ip_v = 4; | ||||
h->ip_hl = sizeof(*h) >> 2; | h->ip_hl = sizeof(*h) >> 2; | ||||
h->ip_tos = IPTOS_LOWDELAY; | h->ip_tos = IPTOS_LOWDELAY; | ||||
h->ip_off = htons(V_path_mtu_discovery ? IP_DF : 0); | h->ip_off = htons(V_path_mtu_discovery ? IP_DF : 0); | ||||
h->ip_len = htons(len); | h->ip_len = htons(len); | ||||
h->ip_ttl = ttl ? ttl : V_ip_defttl; | h->ip_ttl = ttl ? ttl : V_ip_defttl; | ||||
h->ip_sum = 0; | h->ip_sum = 0; | ||||
pfse->pfse_type = PFSE_IP; | |||||
break; | break; | ||||
#endif /* INET */ | #endif /* INET */ | ||||
#ifdef INET6 | #ifdef INET6 | ||||
case AF_INET6: | case AF_INET6: | ||||
/* TCP checksum */ | /* TCP checksum */ | ||||
th->th_sum = in6_cksum(m, IPPROTO_TCP, | th->th_sum = in6_cksum(m, IPPROTO_TCP, | ||||
sizeof(struct ip6_hdr), tlen); | sizeof(struct ip6_hdr), tlen); | ||||
h6->ip6_vfc |= IPV6_VERSION; | h6->ip6_vfc |= IPV6_VERSION; | ||||
h6->ip6_hlim = IPV6_DEFHLIM; | h6->ip6_hlim = IPV6_DEFHLIM; | ||||
break; | |||||
#endif /* INET6 */ | |||||
} | |||||
return (m); | |||||
} | |||||
void | |||||
pf_send_tcp(const struct pf_krule *r, sa_family_t af, | |||||
const struct pf_addr *saddr, const struct pf_addr *daddr, | |||||
u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, | |||||
u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag, | |||||
u_int16_t rtag) | |||||
{ | |||||
struct pf_send_entry *pfse; | |||||
struct mbuf *m; | |||||
m = pf_build_tcp(r, af, saddr, daddr, sport, dport, seq, ack, flags, | |||||
win, mss, ttl, tag, rtag); | |||||
if (m == NULL) | |||||
return; | |||||
/* Allocate outgoing queue entry, mbuf and mbuf tag. */ | |||||
pfse = malloc(sizeof(*pfse), M_PFTEMP, M_NOWAIT); | |||||
if (pfse == NULL) { | |||||
m_freem(m); | |||||
return; | |||||
} | |||||
switch (af) { | |||||
#ifdef INET | |||||
case AF_INET: | |||||
pfse->pfse_type = PFSE_IP; | |||||
break; | |||||
#endif /* INET */ | |||||
#ifdef INET6 | |||||
case AF_INET6: | |||||
pfse->pfse_type = PFSE_IP6; | pfse->pfse_type = PFSE_IP6; | ||||
break; | break; | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
} | } | ||||
pfse->pfse_m = m; | pfse->pfse_m = m; | ||||
pf_send(pfse); | pf_send(pfse); | ||||
} | } | ||||
static void | static void | ||||
pf_return(struct pf_krule *r, struct pf_krule *nr, struct pf_pdesc *pd, | pf_return(struct pf_krule *r, struct pf_krule *nr, struct pf_pdesc *pd, | ||||
struct pf_state_key *sk, int off, struct mbuf *m, struct tcphdr *th, | struct pf_state_key *sk, int off, struct mbuf *m, struct tcphdr *th, | ||||
struct pfi_kkif *kif, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen, | struct pfi_kkif *kif, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen, | ||||
▲ Show 20 Lines • Show All 567 Lines • ▼ Show 20 Lines | #endif /* INET6 */ | ||||
INP_RLOCK_ASSERT(inp); | INP_RLOCK_ASSERT(inp); | ||||
pd->lookup.uid = inp->inp_cred->cr_uid; | pd->lookup.uid = inp->inp_cred->cr_uid; | ||||
pd->lookup.gid = inp->inp_cred->cr_groups[0]; | pd->lookup.gid = inp->inp_cred->cr_groups[0]; | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
return (1); | return (1); | ||||
} | } | ||||
static u_int8_t | u_int8_t | ||||
pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af) | pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af) | ||||
{ | { | ||||
int hlen; | int hlen; | ||||
u_int8_t hdr[60]; | u_int8_t hdr[60]; | ||||
u_int8_t *opt, optlen; | u_int8_t *opt, optlen; | ||||
u_int8_t wscale = 0; | u_int8_t wscale = 0; | ||||
hlen = th_off << 2; /* hlen <= sizeof(hdr) */ | hlen = th_off << 2; /* hlen <= sizeof(hdr) */ | ||||
Show All 23 Lines | default: | ||||
hlen -= optlen; | hlen -= optlen; | ||||
opt += optlen; | opt += optlen; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return (wscale); | return (wscale); | ||||
} | } | ||||
static u_int16_t | u_int16_t | ||||
pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af) | pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af) | ||||
{ | { | ||||
int hlen; | int hlen; | ||||
u_int8_t hdr[60]; | u_int8_t hdr[60]; | ||||
u_int8_t *opt, optlen; | u_int8_t *opt, optlen; | ||||
u_int16_t mss = V_tcp_mssdflt; | u_int16_t mss = V_tcp_mssdflt; | ||||
hlen = th_off << 2; /* hlen <= sizeof(hdr) */ | hlen = th_off << 2; /* hlen <= sizeof(hdr) */ | ||||
▲ Show 20 Lines • Show All 2,828 Lines • ▼ Show 20 Lines | pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) | ||||
switch (h->ip_p) { | switch (h->ip_p) { | ||||
case IPPROTO_TCP: { | case IPPROTO_TCP: { | ||||
if (!pf_pull_hdr(m, off, &pd.hdr.tcp, sizeof(pd.hdr.tcp), | if (!pf_pull_hdr(m, off, &pd.hdr.tcp, sizeof(pd.hdr.tcp), | ||||
&action, &reason, AF_INET)) { | &action, &reason, AF_INET)) { | ||||
log = action != PF_PASS; | log = action != PF_PASS; | ||||
goto done; | goto done; | ||||
} | } | ||||
pd.p_len = pd.tot_len - off - (pd.hdr.tcp.th_off << 2); | pd.p_len = pd.tot_len - off - (pd.hdr.tcp.th_off << 2); | ||||
pd.sport = &pd.hdr.tcp.th_sport; | |||||
pd.dport = &pd.hdr.tcp.th_dport; | |||||
/* Respond to SYN with a syncookie. */ | |||||
if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == TH_SYN && | |||||
pd.dir == PF_IN && pf_synflood_check(&pd)) { | |||||
pf_syncookie_send(m, off, &pd); | |||||
action = PF_DROP; | |||||
break; | |||||
} | |||||
if ((pd.hdr.tcp.th_flags & TH_ACK) && pd.p_len == 0) | if ((pd.hdr.tcp.th_flags & TH_ACK) && pd.p_len == 0) | ||||
pqid = 1; | pqid = 1; | ||||
action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd); | action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd); | ||||
if (action == PF_DROP) | if (action == PF_DROP) | ||||
goto done; | goto done; | ||||
action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd, | action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd, | ||||
&reason); | &reason); | ||||
if (action == PF_PASS) { | if (action == PF_PASS) { | ||||
if (V_pfsync_update_state_ptr != NULL) | if (V_pfsync_update_state_ptr != NULL) | ||||
V_pfsync_update_state_ptr(s); | V_pfsync_update_state_ptr(s); | ||||
r = s->rule.ptr; | r = s->rule.ptr; | ||||
a = s->anchor.ptr; | a = s->anchor.ptr; | ||||
log = s->log; | log = s->log; | ||||
} else if (s == NULL) | } else if (s == NULL) { | ||||
action = pf_test_rule(&r, &s, dir, kif, m, off, &pd, | /* Validate remote SYN|ACK, re-create original SYN if | ||||
&a, &ruleset, inp); | * valid. */ | ||||
if ((pd.hdr.tcp.th_flags & (TH_SYN|TH_ACK|TH_RST)) == | |||||
TH_ACK && pf_syncookie_validate(&pd) && | |||||
pd.dir == PF_IN) { | |||||
struct mbuf *msyn; | |||||
msyn = pf_syncookie_recreate_syn(h->ip_ttl, | |||||
off,&pd); | |||||
if (msyn == NULL) { | |||||
action = PF_DROP; | |||||
break; | |||||
} | |||||
action = pf_test(dir, pflags, ifp, &msyn, inp); | |||||
m_freem(msyn); | |||||
if (action == PF_PASS) { | |||||
action = pf_test_state_tcp(&s, dir, | |||||
kif, m, off, h, &pd, &reason); | |||||
if (action != PF_PASS || s == NULL) { | |||||
action = PF_DROP; | |||||
break; | |||||
} | |||||
s->src.seqhi = ntohl(pd.hdr.tcp.th_ack) | |||||
- 1; | |||||
s->src.seqlo = ntohl(pd.hdr.tcp.th_seq) | |||||
- 1; | |||||
s->src.state = PF_TCPS_PROXY_DST; | |||||
action = pf_synproxy(&pd, &s, &reason); | |||||
if (action != PF_PASS) | |||||
break; | |||||
} | |||||
break; | |||||
} | |||||
else { | |||||
action = pf_test_rule(&r, &s, dir, kif, m, off, | |||||
&pd, &a, &ruleset, inp); | |||||
} | |||||
} | |||||
break; | break; | ||||
} | } | ||||
case IPPROTO_UDP: { | case IPPROTO_UDP: { | ||||
if (!pf_pull_hdr(m, off, &pd.hdr.udp, sizeof(pd.hdr.udp), | if (!pf_pull_hdr(m, off, &pd.hdr.udp, sizeof(pd.hdr.udp), | ||||
&action, &reason, AF_INET)) { | &action, &reason, AF_INET)) { | ||||
log = action != PF_PASS; | log = action != PF_PASS; | ||||
goto done; | goto done; | ||||
▲ Show 20 Lines • Show All 677 Lines • Show Last 20 Lines |