summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/if_pfsync.c7
-rw-r--r--sys/netinet/in.h10
-rw-r--r--sys/netinet/ip_carp.c13
-rw-r--r--sys/netinet/ip_output.c46
-rw-r--r--sys/netinet/ip_var.h5
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 {