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.1 2000/10/18 17:26:29 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 strcpy(ifr
.ifr_name
, oldname
);
103 strcpy(ifr
.ifr_newname
, newname
);
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);
120 struct change
*next
,**pprev
;
121 char ifname
[IFNAMSIZ
+1];
122 unsigned char mac
[6];
124 struct change
*clist
;
126 struct change
*lookupmac(unsigned char *mac
)
129 for (ch
= clist
;ch
;ch
= ch
->next
)
130 if (!memcmp(ch
->mac
, mac
, 6))
135 int addchange(char *p
, struct change
*ch
, char *pos
)
137 if (strchr(ch
->ifname
, ':'))
138 warning(_("alias device %s at %s probably has no mac"),
140 if (parsemac(p
,ch
->mac
) < 0)
141 complain(_("cannot parse MAC `%s' at %s"), p
, pos
);
143 clist
->pprev
= &ch
->next
;
159 ifh
= fopen(fname
, "r");
161 complain(_("opening configuration file %s: %s"),fname
,strerror(errno
));
166 while (getdelim(&line
, &linel
, '\n', ifh
) > 0) {
167 struct change
*ch
= xmalloc(sizeof(struct change
));
170 sprintf(pos
, _("line %d"), linenum
);
172 if ((p
= strchr(line
,'#')) != NULL
)
179 n
= strcspn(p
, " \t");
181 complain(_("interface name too long at line %d"), line
);
182 memcpy(ch
->ifname
, p
, n
);
185 p
+= strspn(p
, " \t");
186 n
= strspn(p
, "0123456789ABCDEFabcdef:");
188 addchange(p
, ch
, pos
);
194 struct option lopt
[] = {
195 {"syslog", 0, NULL
, 's' },
196 {"config-file", 1, NULL
, 'c' },
197 {"help", 0, NULL
, '?' },
203 fprintf(stderr
, _("usage: nameif [-c configurationfile] [-s] {ifname macaddress}"));
207 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)
281 *ch
->pprev
= ch
->next
;
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
));
292 struct change
*ch
= clist
;
294 warning(_("interface '%s' not found"), ch
->ifname
);