2 * Name Interfaces based on MAC address.
3 * Writen 2000 by Andi Kleen.
4 * Subject to the Gnu Public License, version 2.
5 * TODO: make it support token ring etc.
6 * $Id: nameif.c,v 1.4 2003/09/11 03:46:49 ak Exp $
13 #include <sys/syslog.h>
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
22 #include <linux/sockios.h>
26 const char default_conf[] = "/etc/mactab";
27 const char *fname = default_conf;
34 syslog(LOG_ERR,"%s: %m", msg);
41 void complain(char *fmt, ...)
46 vsyslog(LOG_ERR,fmt,ap);
48 vfprintf(stderr,fmt,ap);
55 void warning(char *fmt, ...)
60 vsyslog(LOG_ERR,fmt,ap);
62 vfprintf(stderr,fmt,ap);
68 int parsemac(char *str, unsigned char *mac)
71 while ((s = strsep(&str, ":")) != NULL) {
73 if (sscanf(s,"%x", &byte)!=1 || byte > 0xff)
80 void *xmalloc(unsigned sz)
82 void *p = calloc(sz,1);
83 if (!p) errno=ENOMEM, err("xmalloc");
90 ctl_sk = socket(PF_INET,SOCK_DGRAM,0);
94 #define ifr_newname ifr_ifru.ifru_slave
97 int setname(char *oldname, char *newname)
101 memset(&ifr,0,sizeof(struct ifreq));
102 strncpy(ifr.ifr_name, oldname, IFNAMSIZ);
103 strncpy(ifr.ifr_newname, newname, IFNAMSIZ);
104 return ioctl(ctl_sk, SIOCSIFNAME, &ifr);
107 int getmac(char *name, unsigned char *mac)
112 memset(&ifr,0,sizeof(struct ifreq));
113 strcpy(ifr.ifr_name, name);
114 r = ioctl(ctl_sk, SIOCGIFHWADDR, &ifr);
115 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
122 char ifname[IFNAMSIZ+1];
123 unsigned char mac[6];
125 struct change *clist;
127 struct change *lookupmac(unsigned char *mac)
130 for (ch = clist;ch;ch = ch->next)
131 if (!memcmp(ch->mac, mac, 6))
136 int addchange(char *p, struct change *ch, char *pos)
138 if (strchr(ch->ifname, ':'))
139 warning(_("alias device %s at %s probably has no mac"),
141 if (parsemac(p,ch->mac) < 0)
142 complain(_("cannot parse MAC `%s' at %s"), p, pos);
156 struct change *ch = NULL;
158 ifh = fopen(fname, "r");
160 complain(_("opening configuration file %s: %s"),fname,strerror(errno));
165 while (getdelim(&line, &linel, '\n', ifh) > 0) {
168 sprintf(pos, _("line %d"), linenum);
170 if ((p = strchr(line,'#')) != NULL)
177 n = strcspn(p, " \t");
179 complain(_("interface name too long at line %d"), line);
180 ch = xmalloc(sizeof(struct change));
181 memcpy(ch->ifname, p, n);
184 p += strspn(p, " \t");
185 n = strspn(p, "0123456789ABCDEFabcdef:");
187 addchange(p, ch, pos);
193 struct option lopt[] = {
194 {"syslog", 0, NULL, 's' },
195 {"config-file", 1, NULL, 'c' },
196 {"help", 0, NULL, '?' },
202 fprintf(stderr, _("usage: nameif [-c configurationfile] [-s] {ifname macaddress}\n"));
206 int main(int ac, char **av)
217 int c = getopt_long(ac,av,"c:s",lopt,NULL);
233 openlog("nameif",0,LOG_LOCAL0);
235 while (optind < ac) {
236 struct change *ch = xmalloc(sizeof(struct change));
241 if (strlen(av[optind])+1>IFNAMSIZ)
242 complain(_("interface name `%s' too long"), av[optind]);
243 strcpy(ch->ifname, av[optind]);
245 sprintf(pos,_("argument %d"),optind);
246 addchange(av[optind], ch, pos);
250 if (!clist || fname != default_conf)
253 ifh = fopen("/proc/net/dev", "r");
254 if (!ifh) complain(_("open of /proc/net/dev: %s"), strerror(errno));
258 while (getdelim(&line, &linel, '\n', ifh) > 0) {
260 unsigned char mac[6];
268 n = strcspn(p, ": \t");
272 complain(_("interface name `%s' too long"), p);
274 if (getmac(p, mac) < 0)
282 if (strcmp(p, ch->ifname)) {
283 if (setname(p, ch->ifname) < 0)
284 complain(_("cannot change name of %s to %s: %s"),
285 p, ch->ifname, strerror(errno));
291 struct change *ch = clist;
294 warning(_("interface '%s' not found"), ch->ifname);