Date: Wed, 24 Oct 2001 10:02:50 -0500 (CDT) From: tinguely@web.cs.ndsu.nodak.edu To: FreeBSD-gnats-submit@freebsd.org Cc: tinguely@rrnet.com Subject: bin/31476: ifconfig's lladdr is ethernet specific Message-ID: <200110241502.f9OF2oT04781@web.cs.ndsu.nodak.edu>
next in thread | raw e-mail | index | archive | help
>Number: 31476
>Category: bin
>Synopsis: ifconfig's lladdr is ethernet specific
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Wed Oct 24 08:10:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator: mark tinguely
>Release: FreeBSD 4.4 i386
>Organization:
Mark Tinguely Consulting
>Environment:
System: FreeBSD web.cs.ndsu.nodak.edu 4.4-RELEASE FreeBSD 4.3-STABLE #0: Tue Oct 2 09:13:48 CDT 2001 root@web.cs.ndsu.nodak.edu:/usr/obj/usr/src/sys/WEB44 i386
>Description:
ifconfig's lladdr feature that allows the setting of the link-level
address on an interface. lladdr is documented to not be
ethernet-specific, but the implementation uses ether_aton() which
requires the link level address to be EXACTLY ETHER_ADDR_LEN in
length.
I want to add support for changing a ARCNET link-level address which
is only one octect long.
>How-To-Repeat:
ifconfig INTERFACE lladdr 88
>Fix:
I added a routine to ifconfig called generic_atoi that will
allow abitraty length link-level addresses. generic_atoi() will
assume ETHER_ADDR_LEN length if the caller does not include
an integer to get the count of octets in the specified link-level
address.
The patch also adds "arc" as a new address family. My apologies
for adding two features into one bug-report patch, but they go
hand-in-hand.
The SIOCSIFLLADDR ioctl processing in sys/net/if.c will not
allow a person to set the wrong length link-level address, so
this will not break anything in the kernel.
diff -ur ifconfig.orig/ifconfig.c ifconfig/ifconfig.c
--- ifconfig.orig/ifconfig.c Mon Aug 20 13:38:41 2001
+++ ifconfig/ifconfig.c Wed Oct 24 09:29:11 2001
@@ -157,6 +157,7 @@
void tunnel_status __P((int s));
void usage __P((void));
void ifmaybeload __P((char *name));
+struct ether_addr *generic_aton __P((const char *a, int *cnt));
#ifdef INET6
void in6_fillscopeid __P((struct sockaddr_in6 *sin6));
@@ -292,7 +293,7 @@
typedef void af_getprefix __P((const char *, int));
af_status in_status, at_status, ether_status;
-af_getaddr in_getaddr, at_getaddr, ether_getaddr;
+af_getaddr in_getaddr, at_getaddr, ether_getaddr, arc_getaddr;
#ifndef NO_IPX
af_status ipx_status;
@@ -342,6 +343,8 @@
#endif
{ "ether", AF_LINK, ether_status, ether_getaddr, NULL,
0, SIOCSIFLLADDR, NULL, C(ridreq) },
+ { "arc", AF_LINK, ether_status, arc_getaddr, NULL,
+ 0, SIOCSIFLLADDR, NULL, C(ridreq) },
#if 0 /* XXX conflicts with the media command */
#ifdef USE_IF_MEDIA
{ "media", AF_UNSPEC, media_status, NULL, NULL, }, /* XXX not real!! */
@@ -1059,6 +1062,54 @@
warn("ioctl (set mtu)");
}
+/*
+ * generic_aton() converts up to ETHER_ADDR_LEN ASCII hexadecimal strings
+ * seperated by colons into a ether_addr structure.
+ * generic_aton(a, NULL) is the same as ether_aton(a)
+ * Return values:
+ * function returns converted input from a as an ether_addr structure
+ * cnt returns the number of entries found.
+ */
+struct ether_addr *
+generic_aton(a, cnt)
+ const char *a;
+ int *cnt;
+{
+ int i;
+ char *s, *e;
+ static struct ether_addr o;
+
+ i = 0;
+
+ s = (char *) a;
+ while ((*s == ':' || ishexnumber(*s)) && i < ETHER_ADDR_LEN) {
+ o.octet[i] = strtol(s, &e, 16);
+ s = e;
+ if (*s == ':') {
+ i++;
+ s++;
+ }
+ }
+
+ ++i; /* complete last item */
+
+ if (cnt != NULL) {
+ if ((i == 1 && o.octet[0] == 0) || *s != '\0') {
+ *cnt = 0;
+ return (NULL); /* no info, or too long */
+ } else
+ *cnt = i; /* save number of entries */
+ } else if (i != ETHER_ADDR_LEN)
+ return (NULL);
+
+
+ /* empty unused part of structure */
+ for (; i < ETHER_ADDR_LEN; i++)
+ o.octet[i] = 0;
+
+ return ((struct ether_addr *)&o);
+}
+
void
setiflladdr(val, dummy, s, afp)
const char *val;
@@ -1066,17 +1117,18 @@
int s;
const struct afswtch *afp;
{
+ int i;
struct ether_addr *ea;
- ea = ether_aton(val);
+ ea = generic_aton(val, &i);
if (ea == NULL) {
warn("malformed link-level address");
return;
}
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
- ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
+ ifr.ifr_addr.sa_len = i;
ifr.ifr_addr.sa_family = AF_LINK;
- bcopy(ea, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
+ bcopy(ea, ifr.ifr_addr.sa_data, i);
if (ioctl(s, SIOCSIFLLADDR, (caddr_t)&ifr) < 0)
warn("ioctl (set lladdr)");
@@ -1773,6 +1825,25 @@
sea->sa_family = AF_LINK;
sea->sa_len = ETHER_ADDR_LEN;
bcopy(ea, sea->sa_data, ETHER_ADDR_LEN);
+}
+
+void
+arc_getaddr(addr, which)
+ const char *addr;
+ int which;
+{
+ struct ether_addr *la;
+ struct sockaddr *sea = &ridreq.ifr_addr;
+ int i;
+
+ la = generic_aton(addr, &i);
+ if (la == NULL || i != 1)
+ errx(1, "malformed arc address");
+ if (which == MASK)
+ errx(1, "Arcnet does not use netmasks");
+ sea->sa_family = AF_LINK;
+ sea->sa_len = 1;
+ bcopy(la, sea->sa_data, 1);
}
/* XXX FIXME -- should use strtoul for better parsing. */
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200110241502.f9OF2oT04781>
