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>