diff options
-rw-r--r-- | sys/net/if_pfsync.c | 7 | ||||
-rw-r--r-- | sys/netinet/in.h | 10 | ||||
-rw-r--r-- | sys/netinet/ip_carp.c | 13 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 46 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 5 |
5 files changed, 66 insertions, 15 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c index 6edc36e3512..839d7bbfa1f 100644 --- a/sys/net/if_pfsync.c +++ b/sys/net/if_pfsync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.c,v 1.86 2007/09/15 16:43:51 henning Exp $ */ +/* $OpenBSD: if_pfsync.c,v 1.87 2007/09/18 18:56:02 markus Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff @@ -141,6 +141,10 @@ pfsync_clone_create(struct if_clone *ifc, int unit) pfsyncif->sc_ureq_sent = 0; pfsyncif->sc_bulk_send_next = NULL; pfsyncif->sc_bulk_terminator = NULL; + pfsyncif->sc_imo.imo_membership = (struct in_multi **)malloc( + (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, + M_WAITOK|M_ZERO); + pfsyncif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; ifp = &pfsyncif->sc_if; snprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit); ifp->if_softc = pfsyncif; @@ -176,6 +180,7 @@ pfsync_clone_destroy(struct ifnet *ifp) bpfdetach(ifp); #endif if_detach(ifp); + free(pfsyncif->sc_imo.imo_membership, M_IPMOPTS); free(pfsyncif, M_DEVBUF); pfsyncif = NULL; return (0); diff --git a/sys/netinet/in.h b/sys/netinet/in.h index bbbd2f42888..5cfdf0e66c2 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in.h,v 1.73 2006/10/11 09:34:51 henning Exp $ */ +/* $OpenBSD: in.h,v 1.74 2007/09/18 18:56:02 markus Exp $ */ /* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */ /* @@ -290,7 +290,13 @@ struct ip_opts { */ #define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */ #define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ -#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */ +/* + * The imo_membership vector for each socket starts at IP_MIN_MEMBERSHIPS + * and is dynamically allocated at run-time, bounded by IP_MAX_MEMBERSHIPS, + * and is reallocated when needed, sized according to a power-of-two increment. + */ +#define IP_MIN_MEMBERSHIPS 15 +#define IP_MAX_MEMBERSHIPS 4095 /* * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 5f47ccfc8b1..b5272dd3083 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_carp.c,v 1.149 2007/09/18 09:18:04 mpf Exp $ */ +/* $OpenBSD: ip_carp.c,v 1.150 2007/09/18 18:56:02 markus Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. @@ -846,6 +846,10 @@ carp_clone_create(ifc, unit) #ifdef INET6 sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL; #endif /* INET6 */ + sc->sc_imo.imo_membership = (struct in_multi **)malloc( + (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, + M_WAITOK|M_ZERO); + sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; timeout_set(&sc->sc_ad_tmo, carp_send_ad, sc); timeout_set(&sc->sc_md_tmo, carp_master_down, sc); @@ -879,10 +883,13 @@ carp_clone_create(ifc, unit) int carp_clone_destroy(struct ifnet *ifp) { - carpdetach(ifp->if_softc); + struct carp_softc *sc = ifp->if_softc; + + carpdetach(sc); ether_ifdetach(ifp); if_detach(ifp); - free(ifp->if_softc, M_DEVBUF); + free(sc->sc_imo.imo_membership, M_IPMOPTS); + free(sc, M_DEVBUF); return (0); } diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index e4c01b26373..73490dcc154 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.188 2007/07/20 19:00:35 claudio Exp $ */ +/* $OpenBSD: ip_output.c,v 1.189 2007/09/18 18:56:02 markus Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -1703,6 +1703,7 @@ ip_setmoptions(optname, imop, m) struct ip_mreq *mreq; struct ifnet *ifp; struct ip_moptions *imo = *imop; + struct in_multi **immp; struct route ro; struct sockaddr_in *dst; @@ -1712,13 +1713,17 @@ ip_setmoptions(optname, imop, m) * allocate one and initialize to default values. */ imo = (struct ip_moptions *)malloc(sizeof(*imo), M_IPMOPTS, - M_WAITOK); - + M_WAITOK|M_ZERO); + immp = (struct in_multi **)malloc( + (sizeof(*immp) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, + M_WAITOK|M_ZERO); *imop = imo; imo->imo_multicast_ifp = NULL; imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; imo->imo_num_memberships = 0; + imo->imo_max_memberships = IP_MIN_MEMBERSHIPS; + imo->imo_membership = immp; } switch (optname) { @@ -1834,9 +1839,34 @@ ip_setmoptions(optname, imop, m) error = EADDRINUSE; break; } - if (i == IP_MAX_MEMBERSHIPS) { - error = ETOOMANYREFS; - break; + if (imo->imo_num_memberships == imo->imo_max_memberships) { + struct in_multi **nmships, **omships; + size_t newmax; + /* + * Resize the vector to next power-of-two minus 1. If the + * size would exceed the maximum then we know we've really + * run out of entries. Otherwise, we reallocate the vector. + */ + nmships = NULL; + omships = imo->imo_membership; + newmax = ((imo->imo_max_memberships + 1) * 2) - 1; + if (newmax <= IP_MAX_MEMBERSHIPS) { + nmships = (struct in_multi **)malloc( + sizeof(*nmships) * newmax, M_IPMOPTS, + M_NOWAIT|M_ZERO); + if (nmships != NULL) { + bcopy(omships, nmships, + sizeof(*omships) * + imo->imo_max_memberships); + free(omships, M_IPMOPTS); + imo->imo_membership = nmships; + imo->imo_max_memberships = newmax; + } + } + if (nmships == NULL) { + error = ETOOMANYREFS; + break; + } } /* * Everything looks good; add a new record to the multicast @@ -1910,12 +1940,13 @@ ip_setmoptions(optname, imop, m) } /* - * If all options have default values, no need to keep the mbuf. + * If all options have default values, no need to keep the data. */ if (imo->imo_multicast_ifp == NULL && imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL && imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP && imo->imo_num_memberships == 0) { + free(imo->imo_membership , M_IPMOPTS); free(*imop, M_IPMOPTS); *imop = NULL; } @@ -1984,6 +2015,7 @@ ip_freemoptions(imo) if (imo != NULL) { for (i = 0; i < imo->imo_num_memberships; ++i) in_delmulti(imo->imo_membership[i]); + free(imo->imo_membership, M_IPMOPTS); free(imo, M_IPMOPTS); } } diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index dbe2c64a593..b6ea372229f 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.36 2006/05/29 20:42:27 claudio Exp $ */ +/* $OpenBSD: ip_var.h,v 1.37 2007/09/18 18:56:02 markus Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -96,7 +96,8 @@ struct ip_moptions { u_int8_t imo_multicast_ttl; /* TTL for outgoing multicasts */ u_int8_t imo_multicast_loop; /* 1 => hear sends if a member */ u_int16_t imo_num_memberships; /* no. memberships this socket */ - struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS]; + u_int16_t imo_max_memberships; /* max memberships this socket */ + struct in_multi **imo_membership; /* group memberships */ }; struct ipstat { |