Module Name:    src
Committed By:   msaitoh
Date:           Fri Dec 21 08:58:08 UTC 2018

Modified Files:
        src/sbin/ifconfig: ether.c extern.h ifconfig.c
        src/sys/net: if.c if_ethersubr.c
        src/sys/sys: sockio.h

Log Message:
 Add SIOCSETHERCAP. It's used to change ec_capenable.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sbin/ifconfig/ether.c
cvs rdiff -u -r1.14 -r1.15 src/sbin/ifconfig/extern.h
cvs rdiff -u -r1.237 -r1.238 src/sbin/ifconfig/ifconfig.c
cvs rdiff -u -r1.442 -r1.443 src/sys/net/if.c
cvs rdiff -u -r1.271 -r1.272 src/sys/net/if_ethersubr.c
cvs rdiff -u -r1.35 -r1.36 src/sys/sys/sockio.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/ifconfig/ether.c
diff -u src/sbin/ifconfig/ether.c:1.2 src/sbin/ifconfig/ether.c:1.3
--- src/sbin/ifconfig/ether.c:1.2	Thu Nov  1 13:43:23 2012
+++ src/sbin/ifconfig/ether.c	Fri Dec 21 08:58:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: ether.c,v 1.2 2012/11/01 13:43:23 pgoyette Exp $	*/
+/*	$NetBSD: ether.c,v 1.3 2018/12/21 08:58:08 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 1983, 1993
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ether.c,v 1.2 2012/11/01 13:43:23 pgoyette Exp $");
+__RCSID("$NetBSD: ether.c,v 1.3 2018/12/21 08:58:08 msaitoh Exp $");
 #endif /* not lint */
 
 #include <sys/param.h> 
@@ -40,6 +40,7 @@ __RCSID("$NetBSD: ether.c,v 1.2 2012/11/
 #include <net/if.h> 
 #include <net/if_ether.h>
 
+#include <assert.h>
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
@@ -55,11 +56,99 @@ __RCSID("$NetBSD: ether.c,v 1.2 2012/11/
 
 static void ether_status(prop_dictionary_t, prop_dictionary_t);
 static void ether_constructor(void) __attribute__((constructor));
+static int  setethercaps(prop_dictionary_t, prop_dictionary_t);
 
 static status_func_t status;
+static cmdloop_branch_t branch;
 
 #define MAX_PRINT_LEN 55
 
+static const struct kwinst ethercapskw[] = {
+#if 0 /* notyet */
+	  IFKW("vlan-hwfilter",	ETHERCAP_VLAN_HWFILTER)
+#endif
+	  IFKW("eee",		ETHERCAP_EEE)
+};
+
+struct pkw ethercaps = PKW_INITIALIZER(&ethercaps, "ethercaps", setethercaps,
+    "ethercap", ethercapskw, __arraycount(ethercapskw),
+    &command_root.pb_parser);
+
+void
+do_setethercaps(prop_dictionary_t env)
+{
+	struct eccapreq eccr;
+	prop_data_t d;
+
+	d = (prop_data_t )prop_dictionary_get(env, "ethercaps");
+	if (d == NULL)
+		return;
+
+	assert(sizeof(eccr) == prop_data_size(d));
+
+	memcpy(&eccr, prop_data_data_nocopy(d), sizeof(eccr));
+	if (direct_ioctl(env, SIOCSETHERCAP, &eccr) == -1)
+		err(EXIT_FAILURE, "SIOCSETHERCAP");
+}
+
+static int
+getethercaps(prop_dictionary_t env, prop_dictionary_t oenv,
+    struct eccapreq *oeccr)
+{
+	bool rc;
+	struct eccapreq eccr;
+	const struct eccapreq *tmpeccr;
+	prop_data_t capdata;
+
+	capdata = (prop_data_t)prop_dictionary_get(env, "ethercaps");
+
+	if (capdata != NULL) {
+		tmpeccr = prop_data_data_nocopy(capdata);
+		*oeccr = *tmpeccr;
+		return 0;
+	}
+
+	(void)direct_ioctl(env, SIOCGETHERCAP, &eccr);
+	*oeccr = eccr;
+
+	capdata = prop_data_create_data(&eccr, sizeof(eccr));
+
+	rc = prop_dictionary_set(oenv, "ethercaps", capdata);
+
+	prop_object_release((prop_object_t)capdata);
+
+	return rc ? 0 : -1;
+}
+
+static int
+setethercaps(prop_dictionary_t env, prop_dictionary_t oenv)
+{
+	int64_t ethercap;
+	bool rc;
+	prop_data_t capdata;
+	struct eccapreq eccr;
+
+	rc = prop_dictionary_get_int64(env, "ethercap", &ethercap);
+	assert(rc);
+
+	if (getethercaps(env, oenv, &eccr) == -1)
+		return -1;
+
+	if (ethercap < 0) {
+		ethercap = -ethercap;
+		eccr.eccr_capenable &= ~ethercap;
+	} else
+		eccr.eccr_capenable |= ethercap;
+
+	if ((capdata = prop_data_create_data(&eccr, sizeof(eccr))) == NULL)
+		return -1;
+
+	rc = prop_dictionary_set(oenv, "ethercaps", capdata);
+	prop_object_release((prop_object_t)capdata);
+
+	return rc ? 0 : -1;
+}
+
 void
 ether_status(prop_dictionary_t env, prop_dictionary_t oenv)
 {
@@ -94,6 +183,8 @@ static void
 ether_constructor(void)
 {
 
+	cmdloop_branch_init(&branch, &ethercaps.pk_parser);
+	register_cmdloop_branch(&branch);
 	status_func_init(&status, ether_status);
 	register_status(&status);
 }

Index: src/sbin/ifconfig/extern.h
diff -u src/sbin/ifconfig/extern.h:1.14 src/sbin/ifconfig/extern.h:1.15
--- src/sbin/ifconfig/extern.h:1.14	Fri Aug  7 18:53:37 2009
+++ src/sbin/ifconfig/extern.h	Fri Dec 21 08:58:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.14 2009/08/07 18:53:37 dyoung Exp $	*/
+/*	$NetBSD: extern.h,v 1.15 2018/12/21 08:58:08 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 1983, 1993
@@ -87,6 +87,7 @@ int register_status(status_func_t *);
 int register_usage(usage_func_t *);
 int register_flag(int);
 bool get_flag(int);
+void do_setethercaps(prop_dictionary_t);
 
 extern bool lflag, Nflag, vflag, zflag;
 

Index: src/sbin/ifconfig/ifconfig.c
diff -u src/sbin/ifconfig/ifconfig.c:1.237 src/sbin/ifconfig/ifconfig.c:1.238
--- src/sbin/ifconfig/ifconfig.c:1.237	Thu Nov 15 04:36:46 2018
+++ src/sbin/ifconfig/ifconfig.c	Fri Dec 21 08:58:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: ifconfig.c,v 1.237 2018/11/15 04:36:46 ozaki-r Exp $	*/
+/*	$NetBSD: ifconfig.c,v 1.238 2018/12/21 08:58:08 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
 #ifndef lint
 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
  The Regents of the University of California.  All rights reserved.");
-__RCSID("$NetBSD: ifconfig.c,v 1.237 2018/11/15 04:36:46 ozaki-r Exp $");
+__RCSID("$NetBSD: ifconfig.c,v 1.238 2018/12/21 08:58:08 msaitoh Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -799,6 +799,7 @@ main(int argc, char **argv)
 
 	do_setifpreference(env);
 	do_setifcaps(env);
+	do_setethercaps(env);
 
 	exit(EXIT_SUCCESS);
 }

Index: src/sys/net/if.c
diff -u src/sys/net/if.c:1.442 src/sys/net/if.c:1.443
--- src/sys/net/if.c:1.442	Wed Dec 12 01:46:47 2018
+++ src/sys/net/if.c	Fri Dec 21 08:58:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.442 2018/12/12 01:46:47 rin Exp $	*/
+/*	$NetBSD: if.c,v 1.443 2018/12/21 08:58:08 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.442 2018/12/12 01:46:47 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.443 2018/12/21 08:58:08 msaitoh Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -3230,6 +3230,7 @@ doifioctl(struct socket *so, u_long cmd,
 	case SIOCSLIFPHYADDR:
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
+	case SIOCSETHERCAP:
 	case SIOCSIFMEDIA:
 	case SIOCSDRVSPEC:
 	case SIOCG80211:

Index: src/sys/net/if_ethersubr.c
diff -u src/sys/net/if_ethersubr.c:1.271 src/sys/net/if_ethersubr.c:1.272
--- src/sys/net/if_ethersubr.c:1.271	Thu Nov 15 10:23:56 2018
+++ src/sys/net/if_ethersubr.c	Fri Dec 21 08:58:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ethersubr.c,v 1.271 2018/11/15 10:23:56 maxv Exp $	*/
+/*	$NetBSD: if_ethersubr.c,v 1.272 2018/12/21 08:58:08 msaitoh 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.271 2018/11/15 10:23:56 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.272 2018/12/21 08:58:08 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -1372,6 +1372,48 @@ ether_set_ifflags_cb(struct ethercom *ec
 	ec->ec_ifflags_cb = cb;
 }
 
+static int
+ether_ioctl_reinit(struct ethercom *ec)
+{
+	struct ifnet *ifp = &ec->ec_if;
+	int error;
+
+	switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
+	case IFF_RUNNING:
+		/*
+		 * If interface is marked down and it is running,
+		 * then stop and disable it.
+		 */
+		(*ifp->if_stop)(ifp, 1);
+		break;
+	case IFF_UP:
+		/*
+		 * If interface is marked up and it is stopped, then
+		 * start it.
+		 */
+		return (*ifp->if_init)(ifp);
+	case IFF_UP | IFF_RUNNING:
+		error = 0;
+		if (ec->ec_ifflags_cb != NULL) {
+			error = (*ec->ec_ifflags_cb)(ec);
+			if (error == ENETRESET) {
+				/*
+				 * Reset the interface to pick up
+				 * changes in any other flags that
+				 * affect the hardware state.
+				 */
+				return (*ifp->if_init)(ifp);
+			}
+		} else
+			error = (*ifp->if_init)(ifp);
+		return error;
+	case 0:
+		break;
+	}
+
+	return 0;
+}
+
 /*
  * Common ioctls for Ethernet interfaces.  Note, we must be
  * called at splnet().
@@ -1379,7 +1421,7 @@ ether_set_ifflags_cb(struct ethercom *ec
 int
 ether_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 {
-	struct ethercom *ec = (void *) ifp;
+	struct ethercom *ec = (void *)ifp;
 	struct eccapreq *eccr;
 	struct ifreq *ifr = (struct ifreq *)data;
 	struct if_laddrreq *iflr = data;
@@ -1428,44 +1470,25 @@ ether_ioctl(struct ifnet *ifp, u_long cm
 	case SIOCSIFFLAGS:
 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
 			return error;
-		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
-		case IFF_RUNNING:
-			/*
-			 * If interface is marked down and it is running,
-			 * then stop and disable it.
-			 */
-			(*ifp->if_stop)(ifp, 1);
-			break;
-		case IFF_UP:
-			/*
-			 * If interface is marked up and it is stopped, then
-			 * start it.
-			 */
-			return (*ifp->if_init)(ifp);
-		case IFF_UP | IFF_RUNNING:
-			error = 0;
-			if (ec->ec_ifflags_cb != NULL) {
-				error = (*ec->ec_ifflags_cb)(ec);
-				if (error == ENETRESET) {
-					/*
-					 * Reset the interface to pick up
-					 * changes in any other flags that
-					 * affect the hardware state.
-					 */
-					return (*ifp->if_init)(ifp);
-				}
-			} else
-				error = (*ifp->if_init)(ifp);
-			return error;
-		case 0:
-			break;
-		}
-		return 0;
+		return ether_ioctl_reinit(ec);
 	case SIOCGETHERCAP:
 		eccr = (struct eccapreq *)data;
 		eccr->eccr_capabilities = ec->ec_capabilities;
 		eccr->eccr_capenable = ec->ec_capenable;
 		return 0;
+	case SIOCSETHERCAP:
+		eccr = (struct eccapreq *)data;
+		if ((eccr->eccr_capenable & ~ec->ec_capabilities) != 0)
+			return EINVAL;
+		if (eccr->eccr_capenable == ec->ec_capenable)
+			return 0;
+#if 0 /* notyet */
+		ec->ec_capenable = (ec->ec_capenable & ETHERCAP_CANTCHANGE)
+		    | (eccr->eccr_capenable & ~ETHERCAP_CANTCHANGE);
+#else
+		ec->ec_capenable = eccr->eccr_capenable;
+#endif
+		return ether_ioctl_reinit(ec);
 	case SIOCADDMULTI:
 		return ether_addmulti(ifreq_getaddr(cmd, ifr), ec);
 	case SIOCDELMULTI:

Index: src/sys/sys/sockio.h
diff -u src/sys/sys/sockio.h:1.35 src/sys/sys/sockio.h:1.36
--- src/sys/sys/sockio.h:1.35	Wed Aug  1 23:35:32 2018
+++ src/sys/sys/sockio.h	Fri Dec 21 08:58:08 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: sockio.h,v 1.35 2018/08/01 23:35:32 rjs Exp $	*/
+/*	$NetBSD: sockio.h,v 1.36 2018/12/21 08:58:08 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1990, 1993, 1994
@@ -141,6 +141,7 @@
 
 #define	SIOCGETHERCAP	_IOWR('i', 139, struct eccapreq) /* get ethercap */
 #define SIOCGIFINDEX  _IOWR('i', 140, struct ifreq)   /* get ifnet index */
+#define	SIOCSETHERCAP    _IOW('i', 141, struct eccapreq) /* set ethercap */
 
 #define SIOCGUMBINFO	_IOWR('i', 190, struct ifreq)	/* get MBIM info */
 #define SIOCSUMBPARAM	_IOW('i', 191, struct ifreq)	/* set MBIM param */

Reply via email to