Zbr's days.

About :: TODO :: Blog :: RSS :: Old blog :: Projects :: GIT :: Gallery :: Notes

Wed, 23 Aug 2006

How to get an IP address.


There are some situations, when DHCP can not be used, but board must obtain an IP address, for example when you have an embedded device which is going to be sold into environment where there are no DHCP servers, but you can setup your own applications. One solution is to reinvent DHCP server, but it is possible that new environment actually has DHCP server, but it should not assign an address to the board (read no one wants to notify people when some new system has been installed in the network, and steal IP address from some pool preallocated far ago).
Briefly saying you need to implement something, which must fit into 500kb flash and be possible to obtain addresses from the outside, and it can not use DHCP.
I decided to use multicast - board sends multicast notifications and some userspace application receives them and sends back information with IP addresses. From the first point of view it looks simple, but let's enter wonderland of Linux inet devices.
To be able to send data there must be default route, which can be setup from initrd using rtnetlink. Rtnetlink new route command requires that there must exist an so called inet device (structure which contains IP address information for given network device), which must have an IP address, which in turn can be assigned through rtnetlink. But new adressess assignment requires that device in question must be turned on, which can not be performed through rtnetlink, and only works through ioctl().

So, if you will try to send and receive some data over multicast (for example to get IP address) from initrd, you must:

  • change interface's flags to IFF_UP using ioctl(SIOCGIFFLAGS)
  • set some IP address (DHCP sets 255.255.255.255) using rtnetlink RTM_NEWADDR command
  • set route for given multicast group using rtnetlink RTM_NEWROUTE command
Size of the application, which does exactly what is described above, compiled with gcc-3.4.4 for PPC32, can fit into 500kb (although there is almost no space for something else, except if that "something else" does not work with network).

That is what I was doing (well, I did not exactly that, but put tons of printk() to determine why I only get RTNETLINK answers: No such device and other errors from initrd, but can easily setup new route from normal userspace started over NFS (after DHCP address resolution)), all the time today at my paid work. And of course I participated in, seems to be, endless flood in linux-kernel@ about kevents.

/devel/networking :: Link / Comments ()