From owner-freebsd-questions Wed Mar 28 12:27:34 2001 Delivered-To: freebsd-questions@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 618) id EF06837B719; Wed, 28 Mar 2001 12:27:28 -0800 (PST) Subject: Re: MAC In-Reply-To: <20010329074036.C16495@auckland.ac.nz> from Jamie Walker at "Mar 29, 2001 07:40:36 am" To: jj.walker@auckland.ac.nz (Jamie Walker) Date: Wed, 28 Mar 2001 12:27:28 -0800 (PST) Cc: ajh3@chmod.ath.cx, edward_gess@hotmail.com, freebsd-questions@FreeBSD.ORG X-Mailer: ELM [version 2.4ME+ PL54 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Message-Id: <20010328202728.EF06837B719@hub.freebsd.org> From: wpaul@FreeBSD.ORG (Bill Paul) Sender: owner-freebsd-questions@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > On Wed, Mar 28, 2001 at 09:35:19AM -0600, Andrew Hesford wrote: > > > The MAC address of a network card is hard-wired. Occassionally, the card > > manufacturer will let you change a few digits, but this is dangerous and > > can lead to network problems. > > > > I'm not sure who grants blocks of MAC addresses to card manufacturers, > > it might be the FCC, or it might be ICANN. > > > > The idea behind a MAC address is to give a unique identifier to the > > card, so protocols like TCP can figure out where to send packets. > > from the man pages - ifconfig(8) > > lladdr addr > Set the link-level address on an interface. This can be used to > e.g. set a new MAC address on an ethernet interface, though the > mechanism used is not ethernet-specific. The address addr is > specified as a series of colon-separated hex digits. If the in- > terface is already up when this option is used, it will be > briefly brought down and then brought back up again in order to > insure that the receive filter in the underlying ethernet hard- > ware is properly reprogrammed. > > This usually means the card must be placed in promiscuous mode. No, I'm sorry, you're both wrong. With all currently available ethernet cards, the station address is stored in an EEPROM chip which is separate from the actual ethernet controller chip. The ethernet controller itself has a receive filter which can be programmed to accept or discard frames in a couple of different ways. The exact types of filter capabilities and programming method varies a bit from one chip design to another, but the basics are usually the same: - You can program the filter to accept all frames with a specific unicast distination address. This is usually the station address stored in the EEPROM. The station address is programmed into the filter by the driver when the interface is initialized. - You can program the filter to accept frames sent to a multicast group. The usual method is to use a hash table that is 64, 128, 256 or 512 bits wide. (Cheaper cards usually only use 64 bits.) The driver checks the list of multicast groups that it needs to listen to, runs the multicast address through a hash routine which generates a number between 0 and 63, then it sets the corresponding bit in the chip's hash table. When the chip receives a frame sent to a multicast group, it runs the same hash routine on it, computes the same bit index, then checks to see if the driver set the bit for that index in the hash table. If the bit is set, the chip hands the frame to the host, otherwise it discards it. This is not perfect filtering: sometimes unwanted frames will get through, but the OS is required to perform additional filtering on multicast packets according to the RFCs. - You can program the chip to receive *all* frames regardless of the destination address. This is called promiscuous mode. More complex (and expensive) chips offer other features, such as filtering all broadcast packets, ARP packets, or packets with VLAN tags. Some of them also let you do perfect multicast filtering rather than the hash table method (i.e. you can specify exactly the groups you want to listen for, although there's a limit to how many you can listen for at once, usually 16 or so). The DEC/Intel 21143 actually supports several different driver-selectable filtering methods, which allows the programmer to tailor its behavior depending on application needs. It is the driver's responsibility to read the station address from the EEPROM. In FreeBSD, this happens during in a driver's 'attach' routine, which is called when the driver loads. The address is saved in two places inside the kernel. Later, when the interface is brought up, the driver's 'init' routine will load this address into the chip's receive filter and start the interface running. All you have to do to make the NIC use a different station address is to change what's stored in the kernel, then call the 'init' routine again to reprogram the filter. You do *not* need to put the interface in promiscuous mode, nor do you have to change the contents of the EEPROM. This is not a new idea: anybody who's run SunOS on a SPARC can tell you that you can override the station address on an ethernet interface using 'ifconfig le0 ether ' even as far back as SunOS 4.1.x. That said, there are some *very* old ethernet cards which do not provide a mechanism for programming the unicast/station address filter. These cards load the station address from the EEPROM themselves, and their design simply doesn't offer a way to change it once loaded since the designers didn't deem it necessary. With cards like this, you are forced to use promiscuous mode and software filtering in order to receive packets not meant for your station address. There aren't any cards like this in production today, however: while some chips are able to autoload the station address from the EEPROM (the VIA Rhine is one), the driver can change it later simply by loading a new address into the filter registers. Now, with FreeBSD 4.2 and later, you can do this: # ifconfig foo0 ether 00:00:e8:01:02:03 or # ifconfig foo0 lladdr 00:00:e8:01:02:03 To change the station address on any interface that supports it (which is most of them). For older versions of FreeBSD, you can download: http://www.freebsd.org/~wpaul/mac.tar.gz This is a kernel module and command line utility that lets you do the same thing that ifconfig does now. The module can be built for FreeBSD 2.2.x, FreeBSD 3.0, and FreeBSD 3.2 and up. To use it, do the following: - Unpack the tarball. - For FreeBSD 2.2.x: # cd setmac/module # make; make load - For FreeBSD 3.0: # cd setmac/module_3.0 # make; make load - For FreeBSD 3.2 and later: # cd setmac/module_3.2 # make; make load - Build the setmac utility: # cd setmac/setmac # make - Set the station address: # ./setmac foo0 00:00:e8:01:02:03 This module was originally written for a friend who needed to implement failover support for a custom server application: one machine needed to assume the identity of another machine which had crashed or become unavailable. -Bill To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-questions" in the body of the message