@@ -1,4 +1,4 @@
-/* $NetBSD: if_ethersubr.c,v 1.242.6.4 2018/03/08 14:37:58 martin Exp $ */
+/* $NetBSD: if_ethersubr.c,v 1.242.6.5 2018/03/13 15:40:25 martin Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.242.6.4 2018/03/08 14:37:58 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.242.6.5 2018/03/13 15:40:25 martin Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -192,7 +192,7 @@
{
uint16_t etype = 0;
int error = 0, hdrcmplt = 0;
- uint8_t esrc[6], edst[6];
+ uint8_t esrc[6], edst[6];
struct mbuf *m = m0;
struct mbuf *mcopy = NULL;
struct ether_header *eh;
@@ -301,7 +301,7 @@
break;
#endif
#ifdef NETATALK
- case AF_APPLETALK: {
+ case AF_APPLETALK: {
struct ifaddr *ifa;
int s;
@@ -347,7 +347,7 @@
pserialize_read_exit(s);
KERNEL_UNLOCK_ONE(NULL);
break;
- }
+ }
#endif /* NETATALK */
case pseudo_AF_HDRCMPLT:
hdrcmplt = 1;
@@ -357,7 +357,7 @@
/* FALLTHROUGH */
case AF_UNSPEC:
- memcpy(edst,
+ memcpy(edst,
((const struct ether_header *)dst->sa_data)->ether_dhost,
sizeof(edst));
/* AF_UNSPEC doesn't swap the byte order of the ether_type. */
@@ -401,7 +401,7 @@
eh = mtod(m, struct ether_header *);
/* Note: etype is already in network byte order. */
(void)memcpy(&eh->ether_type, &etype, sizeof(eh->ether_type));
- memcpy(eh->ether_dhost, edst, sizeof(edst));
+ memcpy(eh->ether_dhost, edst, sizeof(edst));
if (hdrcmplt)
memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
else
@@ -538,7 +538,7 @@
return;
- bad:
+bad:
m->m_pkthdr.pattr_class = NULL;
m->m_pkthdr.pattr_hdr = NULL;
m->m_pkthdr.pattr_af = AF_UNSPEC;
@@ -579,7 +579,7 @@
etype = ntohs(eh->ether_type);
ehlen = sizeof(*eh);
- if(__predict_false(earlypkts < 100 || !rnd_initial_entropy)) {
+ if (__predict_false(earlypkts < 100 || !rnd_initial_entropy)) {
rnd_add_data(NULL, eh, ehlen, 0);
earlypkts++;
}
@@ -640,6 +640,7 @@
return;
}
#endif /* NCARP > 0 */
+
if ((m->m_flags & (M_BCAST | M_MCAST | M_PROMISC)) == 0 &&
(ifp->if_flags & IFF_PROMISC) != 0 &&
memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
@@ -695,7 +696,7 @@
/*
* If there is a tag of 0, then the VLAN header was probably
* just being used to store the priority. Extract the ether
- * type, and if IP or IPV6, let them deal with it.
+ * type, and if IP or IPV6, let them deal with it.
*/
if (m->m_len <= sizeof(*evl)
&& EVL_VLANOFTAG(evl->evl_tag) == 0) {
@@ -804,7 +805,7 @@
m_freem(m);
return;
}
-#ifdef GATEWAY
+#ifdef GATEWAY
if (ip6flow_fastforward(&m))
return;
#endif
@@ -878,10 +879,10 @@
m_freem(m);
return;
}
-#else /* ISO || LLC || NETATALK*/
+#else /* LLC || NETATALK */
m_freem(m);
return;
-#endif /* ISO || LLC || NETATALK*/
+#endif /* LLC || NETATALK */
}
if (__predict_true(pktq)) {
@@ -997,9 +998,7 @@
if (ifp->if_bridge)
bridge_ifdetach(ifp);
#endif
-
bpf_detach(ifp);
-
#if NVLAN > 0
if (ec->ec_nvlans)
vlan_ifdetach(ifp);
@@ -1008,12 +1007,12 @@
ETHER_LOCK(ec);
while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) {
LIST_REMOVE(enm, enm_list);
- kmem_intr_free(enm, sizeof(*enm));
+ kmem_free(enm, sizeof(*enm));
ec->ec_multicnt--;
}
ETHER_UNLOCK(ec);
- mutex_destroy(ec->ec_lock);
+ mutex_obj_free(ec->ec_lock);
ifp->if_mowner = NULL;
MOWNER_DETACH(&ec->ec_rx_mowner);
@@ -1113,7 +1112,7 @@
int
ether_aton_r(u_char *dest, size_t len, const char *str)
{
- const u_char *cp = (const void *)str;
+ const u_char *cp = (const void *)str;
u_char *ep;
#define atox(c) (((c) <= '9') ? ((c) - '0') : ((toupper(c) - 'A') + 10))
@@ -1122,20 +1121,22 @@
return ENOSPC;
ep = dest + ETHER_ADDR_LEN;
-
+
while (*cp) {
- if (!isxdigit(*cp))
- return EINVAL;
+ if (!isxdigit(*cp))
+ return EINVAL;
+
*dest = atox(*cp);
cp++;
- if (isxdigit(*cp)) {
- *dest = (*dest << 4) | atox(*cp);
- dest++;
+ if (isxdigit(*cp)) {
+ *dest = (*dest << 4) | atox(*cp);
cp++;
- } else
- dest++;
+ }
+ dest++;
+
if (dest == ep)
- return *cp == '\0' ? 0 : ENAMETOOLONG;
+ return (*cp == '\0') ? 0 : ENAMETOOLONG;
+
switch (*cp) {
case ':':
case '-':
@@ -1143,7 +1144,7 @@
cp++;
break;
}
- }
+ }
return ENOBUFS;
}
@@ -1181,8 +1182,7 @@
*/
memcpy(addrlo, ether_ipmulticast_min, ETHER_ADDR_LEN);
memcpy(addrhi, ether_ipmulticast_max, ETHER_ADDR_LEN);
- }
- else {
+ } else {
ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
memcpy(addrhi, addrlo, ETHER_ADDR_LEN);
}
@@ -1226,10 +1226,7 @@
int error = 0;
/* Allocate out of lock */
- /* XXX still can be called in softint */
- enm = kmem_intr_alloc(sizeof(*enm), KM_SLEEP);
- if (enm == NULL)
- return ENOBUFS;
+ enm = kmem_alloc(sizeof(*enm), KM_SLEEP);
ETHER_LOCK(ec);
error = ether_multiaddr(sa, addrlo, addrhi);
@@ -1243,6 +1240,7 @@
error = EINVAL;
goto out;
}
+
/*
* See if the address range is already in the list.
*/
@@ -1255,24 +1253,27 @@
error = 0;
goto out;
}
+
/*
* Link a new multicast record into the interface's multicast list.
*/
- memcpy(enm->enm_addrlo, addrlo, 6);
- memcpy(enm->enm_addrhi, addrhi, 6);
+ memcpy(enm->enm_addrlo, addrlo, ETHER_ADDR_LEN);
+ memcpy(enm->enm_addrhi, addrhi, ETHER_ADDR_LEN);
enm->enm_refcount = 1;
LIST_INSERT_HEAD(&ec->ec_multiaddrs, enm, enm_list);
ec->ec_multicnt++;
+
/*
* Return ENETRESET to inform the driver that the list has changed
* and its reception filter should be adjusted accordingly.
*/
error = ENETRESET;
enm = NULL;
+
out:
ETHER_UNLOCK(ec);
if (enm != NULL)
- kmem_intr_free(enm, sizeof(*enm));
+ kmem_free(enm, sizeof(*enm));
return error;
}
@@ -1293,7 +1294,7 @@
goto error;
/*
- * Look ur the address in our list.
+ * Look up the address in our list.
*/
ETHER_LOOKUP_MULTI(addrlo, addrhi, ec, enm);
if (enm == NULL) {
@@ -1307,19 +1308,21 @@
error = 0;
goto error;
}
+
/*
* No remaining claims to this record; unlink and free it.
*/
LIST_REMOVE(enm, enm_list);
ec->ec_multicnt--;
ETHER_UNLOCK(ec);
+ kmem_free(enm, sizeof(*enm));
- kmem_intr_free(enm, sizeof(*enm));
/*
* Return ENETRESET to inform the driver that the list has changed
* and its reception filter should be adjusted accordingly.
*/
return ENETRESET;
+
error:
ETHER_UNLOCK(ec);
return error;
@@ -1360,7 +1363,7 @@
#ifdef INET
if (ifa->ifa_addr->sa_family == AF_INET)
arp_ifinit(ifp, ifa);
-#endif /* INET */
+#endif
return 0;
}
@@ -1502,7 +1505,7 @@
* Disable Tx/Rx of VLAN-sized frames.
*/
ec->ec_capenable &= ~ETHERCAP_VLAN_MTU;
-
+
/* Interface is down, defer for later */
if ((ifp->if_flags & IFF_UP) == 0)
return 0;
@@ -1552,16 +1555,23 @@
/*
* ec->ec_lock is a spin mutex so we cannot call sysctl_copyout, which
- * is sleepable, with holding it. Copy data to a local buffer first
- * with holding it and then call sysctl_copyout without holding it.
+ * is sleepable, while holding it. Copy data to a local buffer first
+ * with the lock taken and then call sysctl_copyout without holding it.
*/
retry:
multicnt = ec->ec_multicnt;
- addrs = kmem_alloc(sizeof(*addrs) * multicnt, KM_SLEEP);
+ if (multicnt == 0) {
+ if_put(ifp, &psref);
+ *oldlenp = 0;
+ goto out;
+ }
+
+ addrs = kmem_zalloc(sizeof(*addrs) * multicnt, KM_SLEEP);
+
ETHER_LOCK(ec);
- if (multicnt < ec->ec_multicnt) {
- /* The number of multicast addresses have increased */
+ if (multicnt != ec->ec_multicnt) {
+ /* The number of multicast addresses has changed */
ETHER_UNLOCK(ec);
kmem_free(addrs, sizeof(*addrs) * multicnt);
goto retry;