diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/altq/altq_cbq.h | 2 | ||||
-rw-r--r-- | sys/net/altq/altq_hfsc.h | 2 | ||||
-rw-r--r-- | sys/net/if.h | 2 | ||||
-rw-r--r-- | sys/net/if_bridge.c | 16 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 6 | ||||
-rw-r--r-- | sys/net/if_pflog.h | 4 | ||||
-rw-r--r-- | sys/net/if_pfsync.h | 3 | ||||
-rw-r--r-- | sys/net/pfil.c | 147 | ||||
-rw-r--r-- | sys/net/pfil.h | 7 | ||||
-rw-r--r-- | sys/net/pfvar.h | 87 |
10 files changed, 261 insertions, 15 deletions
diff --git a/sys/net/altq/altq_cbq.h b/sys/net/altq/altq_cbq.h index 51e7cf9..68559e2 100644 --- a/sys/net/altq/altq_cbq.h +++ b/sys/net/altq/altq_cbq.h @@ -190,7 +190,7 @@ struct cbq_getstats { #define CBQ_TIMEOUT 10 #define CBQ_LS_TIMEOUT (20 * hz / 1000) -#define CBQ_MAX_CLASSES 256 +#define CBQ_MAX_CLASSES 2048 #ifdef ALTQ3_COMPAT #define CBQ_MAX_FILTERS 256 diff --git a/sys/net/altq/altq_hfsc.h b/sys/net/altq/altq_hfsc.h index de5e89b..78521f8 100644 --- a/sys/net/altq/altq_hfsc.h +++ b/sys/net/altq/altq_hfsc.h @@ -51,7 +51,7 @@ struct service_curve { /* special class handles */ #define HFSC_NULLCLASS_HANDLE 0 -#define HFSC_MAX_CLASSES 64 +#define HFSC_MAX_CLASSES 2048 /* hfsc class flags */ #define HFCF_RED 0x0001 /* use RED */ diff --git a/sys/net/if.h b/sys/net/if.h index 98ae0a8..5da596a 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -249,7 +249,7 @@ struct if_data { #define IFCAP_CANTCHANGE (IFCAP_NETMAP) -#define IFQ_MAXLEN 50 +#define IFQ_MAXLEN 128 #define IFNET_SLOWHZ 1 /* granularity is 1 second */ /* diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 4fe5e67..d1df805 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -864,6 +864,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } BRIDGE_LOCK(sc); LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + if (bif->bif_ifp->if_type == IFT_GIF) + continue; if (bif->bif_ifp->if_mtu != ifr->ifr_mtu) { log(LOG_NOTICE, "%s: invalid MTU: %u(%s)" " != %d\n", sc->sc_ifp->if_xname, @@ -1155,12 +1157,14 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) } #endif /* Allow the first Ethernet member to define the MTU */ - if (LIST_EMPTY(&sc->sc_iflist)) - sc->sc_ifp->if_mtu = ifs->if_mtu; - else if (sc->sc_ifp->if_mtu != ifs->if_mtu) { - if_printf(sc->sc_ifp, "invalid MTU: %u(%s) != %u\n", - ifs->if_mtu, ifs->if_xname, sc->sc_ifp->if_mtu); - return (EINVAL); + if (ifs->if_type != IFT_GIF) { + if (LIST_EMPTY(&sc->sc_iflist)) + sc->sc_ifp->if_mtu = ifs->if_mtu; + else if (sc->sc_ifp->if_mtu != ifs->if_mtu) { + if_printf(sc->sc_ifp, "invalid MTU: %u(%s) != %u\n", + ifs->if_mtu, ifs->if_xname, sc->sc_ifp->if_mtu); + return (EINVAL); + } } bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT|M_ZERO); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 82c8b3a..27f4411 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -87,6 +87,8 @@ CTASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN); VNET_DEFINE(struct pfil_head, link_pfil_hook); /* Packet filter hooks */ +SYSCTL_DECL(_net_link); + /* netgraph node hooks for ng_ether(4) */ void (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp); void (*ng_ether_input_orphan_p)(struct ifnet *ifp, struct mbuf *m); @@ -702,6 +704,9 @@ vnet_ether_init(__unused void *arg) if ((i = pfil_head_register(&V_link_pfil_hook)) != 0) printf("%s: WARNING: unable to register pfil link hook, " "error %d\n", __func__, i); + else + pfil_head_export_sysctl(&V_link_pfil_hook, + SYSCTL_STATIC_CHILDREN(_net_link)); #ifdef VIMAGE netisr_register_vnet(ðer_nh); #endif @@ -972,7 +977,6 @@ ether_reassign(struct ifnet *ifp, struct vnet *new_vnet, char *unused __unused) } #endif -SYSCTL_DECL(_net_link); SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); #if 0 diff --git a/sys/net/if_pflog.h b/sys/net/if_pflog.h index 0faeb7d..326b551 100644 --- a/sys/net/if_pflog.h +++ b/sys/net/if_pflog.h @@ -40,10 +40,14 @@ struct pfloghdr { char ruleset[PFLOG_RULESET_NAME_SIZE]; u_int32_t rulenr; u_int32_t subrulenr; +#ifdef PF_USER_INFO uid_t uid; pid_t pid; uid_t rule_uid; pid_t rule_pid; +#else + u_int32_t ridentifier; +#endif u_int8_t dir; u_int8_t pad[3]; }; diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h index 5c4ba63..74be9b7 100644 --- a/sys/net/if_pfsync.h +++ b/sys/net/if_pfsync.h @@ -235,6 +235,9 @@ struct pfsyncreq { char pfsyncr_syncdev[IFNAMSIZ]; struct in_addr pfsyncr_syncpeer; int pfsyncr_maxupdates; +#define PFSYNCF_OK 0x00000001 +#define PFSYNCF_DEFER 0x00000002 +#define PFSYNCF_PUSH 0x00000004 int pfsyncr_defer; }; diff --git a/sys/net/pfil.c b/sys/net/pfil.c index 248d183..94a95ac 100644 --- a/sys/net/pfil.c +++ b/sys/net/pfil.c @@ -34,6 +34,7 @@ #include <sys/errno.h> #include <sys/lock.h> #include <sys/malloc.h> +#include <sys/sbuf.h> #include <sys/rmlock.h> #include <sys/socket.h> #include <sys/socketvar.h> @@ -79,7 +80,7 @@ pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp, KASSERT(ph->ph_nhooks >= 0, ("Pfil hook count dropped < 0")); for (pfh = pfil_chain_get(dir, ph); pfh != NULL; pfh = TAILQ_NEXT(pfh, pfil_chain)) { - if (pfh->pfil_func != NULL) { + if (!(pfh->pfil_flags & PFIL_DISABLED) && pfh->pfil_func != NULL) { rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir, inp); if (rv != 0 || m == NULL) @@ -212,6 +213,140 @@ pfil_head_unregister(struct pfil_head *ph) return (0); } +static int +pfil_sysctl_handler(SYSCTL_HANDLER_ARGS) +{ + struct rm_priotracker rmpt; + struct pfil_head *ph; + struct packet_filter_hook *pfh, *pfhtmp; + struct sbuf *sb; + pfil_chain_t npfl, *pfl; + char *new_order, *elm, *parse; + int i = 0, err = 0, hintlen, reqlen; + + hintlen = 0; + + ph = (struct pfil_head *)arg1; + if (ph == NULL || !PFIL_HOOKED(ph)) { + err = SYSCTL_OUT(req, "", 2); + return (err); + } + + if (arg2 == PFIL_IN) + pfl = &ph->ph_in; + else + pfl = &ph->ph_out; + + if (TAILQ_EMPTY(pfl)) { + err = SYSCTL_OUT(req, "", 2); + return (err); + } + + /* + * NOTE: This is needed to avoid witness(4) warnings. + */ + PFIL_RLOCK(ph, &rmpt); + TAILQ_FOREACH(pfh, pfl, pfil_chain) { + if (pfh->pfil_name != NULL) + hintlen = strlen(pfh->pfil_name); + else + hintlen += 2; + } + PFIL_RUNLOCK(ph, &rmpt); + + sb = sbuf_new(NULL, NULL, hintlen + 1, SBUF_AUTOEXTEND); + if (sb == NULL) + return (EINVAL); + + PFIL_RLOCK(ph, &rmpt); + TAILQ_FOREACH(pfh, pfl, pfil_chain) { + if (i > 0) + sbuf_printf(sb, ", "); + if (pfh->pfil_name != NULL) + sbuf_printf(sb, "%s%s", pfh->pfil_name, + pfh->pfil_flags & PFIL_DISABLED ? "*" : ""); + else + sbuf_printf(sb, "%s%s", "NA", + pfh->pfil_flags & PFIL_DISABLED ? "*" : ""); + i++; + } + PFIL_RUNLOCK(ph, &rmpt); + + sbuf_finish(sb); + + /* hint for sensible write buffer sizes */ + hintlen = sbuf_len(sb) + i * 2; + err = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); + sbuf_delete(sb); + + if (err || !req->newptr) + return (err); + + if ((reqlen = req->newlen - req->newidx) > hintlen) + return (E2BIG); + new_order = malloc(reqlen + 1, M_TEMP, M_WAITOK|M_ZERO); + + err = SYSCTL_IN(req, new_order, reqlen); + if (err) + goto error; + new_order[reqlen] = '\0'; /* Just in case */ + parse = new_order; + + TAILQ_INIT(&npfl); + PFIL_WLOCK(ph); + while ((elm = strsep(&parse, " \t,")) != NULL) { + if (*elm == '\0') + continue; + TAILQ_FOREACH_SAFE(pfh, pfl, pfil_chain, pfhtmp) { + if (pfh->pfil_name != NULL) { + if (!strcmp(pfh->pfil_name, elm)) { + TAILQ_REMOVE(pfl, pfh, pfil_chain); + TAILQ_INSERT_TAIL(&npfl, pfh, pfil_chain); + pfh->pfil_flags &= ~PFIL_DISABLED; + break; + } + } else { + if (!strcmp(elm, "NA")) { + TAILQ_REMOVE(pfl, pfh, pfil_chain); + TAILQ_INSERT_TAIL(&npfl, pfh, pfil_chain); + pfh->pfil_flags &= ~PFIL_DISABLED; + break; + } + } + } + } + + TAILQ_FOREACH_SAFE(pfh, pfl, pfil_chain, pfhtmp) { + pfh->pfil_flags |= PFIL_DISABLED; + TAILQ_REMOVE(pfl, pfh, pfil_chain); + TAILQ_INSERT_TAIL(&npfl, pfh, pfil_chain); + } + + TAILQ_CONCAT(pfl, &npfl, pfil_chain); + +error: + PFIL_WUNLOCK(ph); + free(new_order, M_TEMP); + return (err); +} + +void +pfil_head_export_sysctl(struct pfil_head *ph, struct sysctl_oid_list *parent) +{ + struct sysctl_oid *root; + + root = SYSCTL_ADD_NODE(&ph->ph_clist, parent, OID_AUTO, "pfil", + CTLFLAG_RW, 0, "pfil(9) management"); + SYSCTL_ADD_PROC((void *)&ph->ph_clist, SYSCTL_CHILDREN(root), OID_AUTO, + "inbound", CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_SECURE3, + (void *)ph, PFIL_IN, pfil_sysctl_handler, "A", + "Inbound filter hooks"); + SYSCTL_ADD_PROC((void *)&ph->ph_clist, SYSCTL_CHILDREN(root), OID_AUTO, + "outbound", CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_SECURE3, + (void *)ph, PFIL_OUT, pfil_sysctl_handler, "A", + "Outbound filter hooks"); +} + /* * pfil_head_get() returns the pfil_head for a given key/dlt. */ @@ -239,6 +374,12 @@ pfil_head_get(int type, u_long val) int pfil_add_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph) { + return (pfil_add_named_hook(func, arg, NULL, flags, ph)); +} + +int +pfil_add_named_hook(pfil_func_t func, void *arg, char *name, int flags, struct pfil_head *ph) +{ struct packet_filter_hook *pfh1 = NULL; struct packet_filter_hook *pfh2 = NULL; int err; @@ -263,6 +404,8 @@ pfil_add_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph) if (flags & PFIL_IN) { pfh1->pfil_func = func; pfh1->pfil_arg = arg; + pfh1->pfil_name = name; + pfh1->pfil_flags &= ~PFIL_DISABLED; err = pfil_chain_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT); if (err) goto locked_error; @@ -271,6 +414,8 @@ pfil_add_hook(pfil_func_t func, void *arg, int flags, struct pfil_head *ph) if (flags & PFIL_OUT) { pfh2->pfil_func = func; pfh2->pfil_arg = arg; + pfh2->pfil_name = name; + pfh2->pfil_flags &= ~PFIL_DISABLED; err = pfil_chain_add(&ph->ph_out, pfh2, flags & ~PFIL_IN); if (err) { if (flags & PFIL_IN) diff --git a/sys/net/pfil.h b/sys/net/pfil.h index c9a1b65..ff260ce 100644 --- a/sys/net/pfil.h +++ b/sys/net/pfil.h @@ -38,6 +38,7 @@ #include <sys/_mutex.h> #include <sys/lock.h> #include <sys/rmlock.h> +#include <sys/sysctl.h> struct mbuf; struct ifnet; @@ -55,11 +56,14 @@ struct packet_filter_hook { TAILQ_ENTRY(packet_filter_hook) pfil_chain; pfil_func_t pfil_func; void *pfil_arg; + int pfil_flags; + char *pfil_name; }; #define PFIL_IN 0x00000001 #define PFIL_OUT 0x00000002 #define PFIL_WAITOK 0x00000004 +#define PFIL_DISABLED 0x00000008 #define PFIL_ALL (PFIL_IN|PFIL_OUT) typedef TAILQ_HEAD(pfil_chain, packet_filter_hook) pfil_chain_t; @@ -85,6 +89,7 @@ struct pfil_head { struct rmlock ph_lock; /* Private lock storage */ int flags; #endif + struct sysctl_ctx_list ph_clist; union { u_long phu_val; void *phu_ptr; @@ -96,7 +101,9 @@ struct pfil_head { /* Public functions for pfil hook management by packet filters. */ struct pfil_head *pfil_head_get(int, u_long); +void pfil_head_export_sysctl(struct pfil_head *, struct sysctl_oid_list *); int pfil_add_hook(pfil_func_t, void *, int, struct pfil_head *); +int pfil_add_named_hook(pfil_func_t, void *, char *, int, struct pfil_head *); int pfil_remove_hook(pfil_func_t, void *, int, struct pfil_head *); #define PFIL_HOOKED(p) ((p)->ph_nhooks > 0) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index ed23eb5..a6c95ac 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -329,6 +329,14 @@ struct pf_rule_gid { u_int8_t op; }; +struct pf_rule_ieee8021q_pcp { + u_int8_t pcp[2]; + u_int8_t op; +#define SETPCP_VALID 0x80 /* Set if PCP value in field is valid. */ +#define SETPCP_PCP_MASK 0x07 /* Mask to retrieve pcp if SETPCP_VALID. */ + u_int8_t setpcp; +}; + struct pf_rule_addr { struct pf_addr_wrap addr; u_int16_t port[2]; @@ -468,6 +476,13 @@ struct pf_osfp_ioctl { int fp_getnum; /* DIOCOSFPGET number */ }; +struct pf_rule_actions { + u_int16_t qid; + u_int16_t pqid; + u_int32_t pdnpipe; + u_int32_t dnpipe; + u_int8_t flags; +}; union pf_rule_ptr { struct pf_rule *ptr; @@ -491,6 +506,7 @@ struct pf_rule { union pf_rule_ptr skip[PF_SKIP_COUNT]; #define PF_RULE_LABEL_SIZE 64 char label[PF_RULE_LABEL_SIZE]; + char schedule[PF_RULE_LABEL_SIZE]; char ifname[IFNAMSIZ]; char qname[PF_QNAME_SIZE]; char pqname[PF_QNAME_SIZE]; @@ -523,12 +539,21 @@ struct pf_rule { u_int32_t limit; u_int32_t seconds; } max_src_conn_rate; - u_int32_t qid; - u_int32_t pqid; + u_int16_t qid; + u_int16_t pqid; + u_int32_t dnpipe; + u_int32_t pdnpipe; +#define PFRULE_DN_IS_PIPE 0x00000010 +#define PFRULE_DN_IS_QUEUE 0x00000020 + u_int32_t free_flags; u_int32_t rt_listid; u_int32_t nr; u_int32_t prob; +#ifdef PF_USER_INFO uid_t cuid; +#else + u_int32_t cuid; +#endif pid_t cpid; counter_u64_t states_cur; @@ -569,6 +594,29 @@ struct pf_rule { u_int8_t allow_opts; u_int8_t rt; u_int8_t return_ttl; + +#ifndef DSCP_EF +/* Copied from altq_cdnr.h */ +/* diffserve code points */ +#define DSCP_MASK 0xfc +#define DSCP_CUMASK 0x03 +#define DSCP_VA 0xb0 +#define DSCP_EF 0xb8 +#define DSCP_AF11 0x28 +#define DSCP_AF12 0x30 +#define DSCP_AF13 0x38 +#define DSCP_AF21 0x48 +#define DSCP_AF22 0x50 +#define DSCP_AF23 0x58 +#define DSCP_AF31 0x68 +#define DSCP_AF32 0x70 +#define DSCP_AF33 0x78 +#define DSCP_AF41 0x88 +#define DSCP_AF42 0x90 +#define DSCP_AF43 0x98 +#define AF_CLASSMASK 0xe0 +#define AF_DROPPRECMASK 0x18 +#endif u_int8_t tos; u_int8_t set_tos; u_int8_t anchor_relative; @@ -583,6 +631,8 @@ struct pf_rule { u_int16_t port; } divert; + struct pf_rule_ieee8021q_pcp ieee8021q_pcp; + uint64_t u_states_cur; uint64_t u_states_tot; uint64_t u_src_nodes; @@ -605,6 +655,13 @@ struct pf_rule { #define PFRULE_REASSEMBLE_TCP 0x1000 #define PFRULE_SET_TOS 0x2000 +/* rule flags for TOS or DSCP differentiation */ +#define PFRULE_TOS 0x2000 +#define PFRULE_DSCP 0x4000 + +/* rule flags for handling ALTQ hashing required by certain disciplines */ +#define PFRULE_ALTQ_HASH 0x8000 + /* rule flags again */ #define PFRULE_IFBOUND 0x00010000 /* if-bound */ #define PFRULE_STATESLOPPY 0x00020000 /* sloppy state tracking */ @@ -709,7 +766,13 @@ struct pf_state { u_int64_t id; u_int32_t creatorid; u_int8_t direction; - u_int8_t pad[3]; + u_int8_t pad[2]; + u_int8_t local_flags; +#define PFSTATE_DIVERT_ALTQ 0x10 +#define PFSTATE_DIVERT_DNCOOKIE 0x20 +#define PFSTATE_DIVERT_ACTION 0x40 +#define PFSTATE_DIVERT_TAG 0x80 +#define PFSTATE_DIVERT_MASK 0xFF00 u_int refs; TAILQ_ENTRY(pf_state) sync_list; @@ -731,7 +794,12 @@ struct pf_state { u_int32_t creation; u_int32_t expire; u_int32_t pfsync_time; + u_int16_t qid; + u_int16_t pqid; + u_int32_t pdnpipe; + u_int32_t dnpipe; u_int16_t tag; + u_int16_t divert_cookie; u_int8_t log; u_int8_t state_flags; #define PFSTATE_ALLOWOPTS 0x01 @@ -744,7 +812,7 @@ struct pf_state { /* XXX */ u_int8_t sync_updates; - u_int8_t _tail[3]; + u_int8_t _tail; }; /* @@ -1080,11 +1148,13 @@ struct pfi_kif { #define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */ struct pf_pdesc { +#ifdef PF_USER_INFO struct { int done; uid_t uid; gid_t gid; } lookup; +#endif u_int64_t tot_len; /* Make Mickey money */ union { struct tcphdr *tcp; @@ -1102,6 +1172,7 @@ struct pf_pdesc { u_int16_t *sport; u_int16_t *dport; struct pf_mtag *pf_mtag; + struct pf_rule_actions act; u_int32_t p_len; /* total length of payload */ @@ -1253,6 +1324,11 @@ struct pfioc_state_kill { u_int psk_killed; }; +struct pfioc_schedule_kill { + int numberkilled; + char schedule[PF_RULE_LABEL_SIZE]; +}; + struct pfioc_states { int ps_len; union { @@ -1437,6 +1513,7 @@ struct pf_ifspeed { u_int32_t baudrate; }; #define DIOCGIFSPEED _IOWR('D', 92, struct pf_ifspeed) +#define DIOCKILLSCHEDULE _IOWR('D', 96, struct pfioc_schedule_kill) #ifdef _KERNEL LIST_HEAD(pf_src_node_list, pf_src_node); @@ -1595,6 +1672,8 @@ int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *, int pf_match_addr_range(struct pf_addr *, struct pf_addr *, struct pf_addr *, sa_family_t); int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t); +int pf_match_ieee8021q_pcp(u_int8_t, u_int8_t, u_int8_t, struct mbuf *); +int pf_ieee8021q_setpcp(struct mbuf *m, struct pf_rule *r); void pf_normalize_init(void); void pf_normalize_cleanup(void); |