Index: sys/netgraph/ng_bridge.c =================================================================== --- sys/netgraph/ng_bridge.c (revision 351934) +++ sys/netgraph/ng_bridge.c (working copy) @@ -101,12 +101,13 @@ /* Per-node private data */ struct ng_bridge_private { struct ng_bridge_bucket *tab; /* hash table bucket array */ - struct ng_bridge_link *links[NG_BRIDGE_MAX_LINKS]; + struct ng_bridge_link **links; struct ng_bridge_config conf; /* node configuration */ node_p node; /* netgraph node */ u_int numHosts; /* num entries in table */ u_int numBuckets; /* num buckets in table */ u_int hashMask; /* numBuckets - 1 */ + u_int maxLinks; /* allocated links */ int numLinks; /* num connected links */ int persistent; /* can exist w/o hooks */ struct callout timer; /* one second periodic timer */ @@ -133,6 +134,7 @@ /* Other internal functions */ static struct ng_bridge_host *ng_bridge_get(priv_p priv, const u_char *addr); static int ng_bridge_put(priv_p priv, const u_char *addr, int linkNum); +static int ng_bridge_morelinks(node_p node, int linkNum); static void ng_bridge_rehash(priv_p priv); static void ng_bridge_remove_hosts(priv_p priv, int linkNum); static void ng_bridge_timeout(node_p node, hook_p hook, void *arg1, int arg2); @@ -200,16 +202,8 @@ }; /* Parse type for struct ng_bridge_config */ -static const struct ng_parse_fixedarray_info ng_bridge_ipfwary_type_info = { - &ng_parse_uint8_type, - NG_BRIDGE_MAX_LINKS -}; -static const struct ng_parse_type ng_bridge_ipfwary_type = { - &ng_parse_fixedarray_type, - &ng_bridge_ipfwary_type_info -}; static const struct ng_parse_struct_field ng_bridge_config_type_fields[] - = NG_BRIDGE_CONFIG_TYPE_INFO(&ng_bridge_ipfwary_type); + = NG_BRIDGE_CONFIG_TYPE_INFO; static const struct ng_parse_type ng_bridge_config_type = { &ng_parse_struct_type, &ng_bridge_config_type_fields @@ -315,6 +309,9 @@ ng_callout_init(&priv->timer); /* Allocate and initialize hash table, etc. */ + priv->maxLinks = NG_BRIDGE_INC_LINKS; + priv->links = malloc(priv->maxLinks * sizeof(*priv->links), + M_NETGRAPH_BRIDGE, M_WAITOK | M_ZERO); priv->tab = malloc(MIN_BUCKETS * sizeof(*priv->tab), M_NETGRAPH_BRIDGE, M_WAITOK | M_ZERO); priv->numBuckets = MIN_BUCKETS; @@ -357,13 +354,17 @@ const char *cp; char *eptr; u_long linkNum; + int error; cp = name + strlen(NG_BRIDGE_HOOK_LINK_PREFIX); if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) return (EINVAL); linkNum = strtoul(cp, &eptr, 10); - if (*eptr != '\0' || linkNum >= NG_BRIDGE_MAX_LINKS) + if (*eptr != '\0') return (EINVAL); + if (linkNum >= priv->maxLinks) + if ((error = ng_bridge_morelinks(node, linkNum)) != 0) + return error; if (priv->links[linkNum] != NULL) return (EISCONN); priv->links[linkNum] = malloc(sizeof(*priv->links[linkNum]), @@ -412,7 +413,6 @@ case NGM_BRIDGE_SET_CONFIG: { struct ng_bridge_config *conf; - int i; if (msg->header.arglen != sizeof(struct ng_bridge_config)) { @@ -421,8 +421,6 @@ } conf = (struct ng_bridge_config *)msg->data; priv->conf = *conf; - for (i = 0; i < NG_BRIDGE_MAX_LINKS; i++) - priv->conf.ipfw[i] = !!priv->conf.ipfw[i]; break; } case NGM_BRIDGE_RESET: @@ -433,7 +431,7 @@ ng_bridge_remove_hosts(priv, -1); /* Reset all loop detection counters and stats */ - for (i = 0; i < NG_BRIDGE_MAX_LINKS; i++) { + for (i = 0; i < priv->maxLinks; i++) { if (priv->links[i] == NULL) continue; priv->links[i]->loopCount = 0; @@ -455,7 +453,7 @@ break; } linkNum = *((u_int32_t *)msg->data); - if (linkNum < 0 || linkNum >= NG_BRIDGE_MAX_LINKS) { + if (linkNum < 0 || linkNum >= priv->maxLinks) { error = EINVAL; break; } @@ -539,7 +537,7 @@ NGI_GET_M(item, m); /* Get link number */ linkNum = (intptr_t)NG_HOOK_PRIVATE(hook); - KASSERT(linkNum >= 0 && linkNum < NG_BRIDGE_MAX_LINKS, + KASSERT(linkNum >= 0 && linkNum < priv->maxLinks, ("%s: linkNum=%u", __func__, linkNum)); link = priv->links[linkNum]; KASSERT(link != NULL, ("%s: link%d null", __func__, linkNum)); @@ -779,6 +777,7 @@ ng_uncallout(&priv->timer, node); NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); + free(priv->links, M_NETGRAPH_BRIDGE); free(priv->tab, M_NETGRAPH_BRIDGE); free(priv, M_NETGRAPH_BRIDGE); return (0); @@ -795,7 +794,7 @@ /* Get link number */ linkNum = (intptr_t)NG_HOOK_PRIVATE(hook); - KASSERT(linkNum >= 0 && linkNum < NG_BRIDGE_MAX_LINKS, + KASSERT(linkNum >= 0 && linkNum < priv->maxLinks, ("%s: linkNum=%u", __func__, linkNum)); /* Remove all hosts associated with this link */ @@ -944,6 +943,33 @@ ******************************************************************/ /* + * Expand table of links, if necessary + */ +static int +ng_bridge_morelinks(node_p node, int linkNum) +{ + priv_p priv = NG_NODE_PRIVATE(node); + int newsize = priv->maxLinks + NG_BRIDGE_INC_LINKS; + void * newp; + + if (linkNum >= newsize || linkNum < 0) + return (EINVAL); + + if (linkNum < priv->maxLinks) + return 0; + + newp = realloc(priv->links, + newsize * sizeof(*priv->links), + M_NETGRAPH_BRIDGE, M_WAITOK | M_ZERO); + if(newp == NULL) /* old array intact */ + return (ENOMEM); + + priv->links = newp; + priv->maxLinks = newsize; + return 0; +} + +/* * Remove all hosts associated with a specific link from the hashtable. * If linkNum == -1, then remove all hosts in the table. */ @@ -1015,7 +1041,7 @@ ng_bridge_rehash(priv); /* Decrease loop counter on muted looped back links */ - for (counter = linkNum = 0; linkNum < NG_BRIDGE_MAX_LINKS; linkNum++) { + for (counter = linkNum = 0; linkNum < priv->maxLinks; linkNum++) { struct ng_bridge_link *const link = priv->links[linkNum]; if (link != NULL) { Index: sys/netgraph/ng_bridge.h =================================================================== --- sys/netgraph/ng_bridge.h (revision 351934) +++ sys/netgraph/ng_bridge.h (working copy) @@ -45,18 +45,17 @@ /* Node type name and magic cookie */ #define NG_BRIDGE_NODE_TYPE "bridge" -#define NGM_BRIDGE_COOKIE 967239368 +#define NGM_BRIDGE_COOKIE 1569321993 /* Hook names */ #define NG_BRIDGE_HOOK_LINK_PREFIX "link" /* append decimal integer */ #define NG_BRIDGE_HOOK_LINK_FMT "link%d" /* for use with printf(3) */ -/* Maximum number of supported links */ -#define NG_BRIDGE_MAX_LINKS 32 +/* Increment for number of supported links */ +#define NG_BRIDGE_INC_LINKS 32 /* Node configuration structure */ struct ng_bridge_config { - u_char ipfw[NG_BRIDGE_MAX_LINKS]; /* enable ipfw */ u_char debugLevel; /* debug level */ u_int32_t loopTimeout; /* link loopback mute time */ u_int32_t maxStaleness; /* max host age before nuking */ @@ -64,8 +63,7 @@ }; /* Keep this in sync with the above structure definition */ -#define NG_BRIDGE_CONFIG_TYPE_INFO(ainfo) { \ - { "ipfw", (ainfo) }, \ +#define NG_BRIDGE_CONFIG_TYPE_INFO { \ { "debugLevel", &ng_parse_uint8_type }, \ { "loopTimeout", &ng_parse_uint32_type }, \ { "maxStaleness", &ng_parse_uint32_type }, \ Index: share/man/man4/ng_bridge.4 =================================================================== --- share/man/man4/ng_bridge.4 (revision 351934) +++ share/man/man4/ng_bridge.4 (working copy) @@ -76,14 +76,12 @@ .Xr ipfirewall 4 mechanism on a per-link basis is not yet implemented. .Sh HOOKS -This node type supports up to -.Dv NG_BRIDGE_MAX_LINKS -hooks. +This node type supports an unlimited number of hooks. Each connected hook represents a bridged link. The hooks are named .Dv link0 , .Dv link1 , -etc. +etc. and are allocated sequentially. Typically these hooks are connected to the .Dv lower hooks of one or more @@ -106,7 +104,6 @@ .Bd -literal -offset 0n /* Node configuration structure */ struct ng_bridge_config { - u_char ipfw[NG_BRIDGE_MAX_LINKS]; /* enable ipfw */ u_char debugLevel; /* debug level */ uint32_t loopTimeout; /* link loopback mute time */ uint32_t maxStaleness; /* max host age before nuking */ @@ -115,11 +112,6 @@ .Ed .Pp The -.Dv ipfw -array enables -.Xr ipfirewall 4 -processing of IP packets received on the corresponding links. -The .Dv debugLevel field sets the debug level on the node. At level of 2 or greater, detected loops are logged.