man/pt_BR/ifconfig.8: remove untranslated paragraph
[platform/upstream/net-tools.git] / nameif.c
1 /* 
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 $
7  */ 
8 #ifndef _GNU_SOURCE 
9 #define _GNU_SOURCE
10 #endif
11 #include <stdio.h>
12 #include <getopt.h>
13 #include <sys/syslog.h>
14 #include <errno.h>
15 #include <stdlib.h>
16 #include <ctype.h>
17 #include <string.h>
18 #include <stdarg.h>
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
21 #include <net/if.h>
22 #include <linux/sockios.h>
23 #include <errno.h>
24 #include "intl.h" 
25
26 const char default_conf[] = "/etc/mactab"; 
27 const char *fname = default_conf; 
28 int use_syslog; 
29 int ctl_sk = -1; 
30
31 void err(char *msg) 
32
33         if (use_syslog) { 
34                 syslog(LOG_ERR,"%s: %m", msg); 
35         } else { 
36                 perror(msg); 
37         } 
38         exit(1); 
39 }
40
41 void complain(char *fmt, ...) 
42
43         va_list ap;
44         va_start(ap,fmt);
45         if (use_syslog) { 
46                 vsyslog(LOG_ERR,fmt,ap);
47         } else {
48                 vfprintf(stderr,fmt,ap);
49                 fputc('\n',stderr); 
50         }
51         va_end(ap); 
52         exit(1);
53
54
55 void warning(char *fmt, ...) 
56
57         va_list ap;
58         va_start(ap,fmt);
59         if (use_syslog) { 
60                 vsyslog(LOG_ERR,fmt,ap);
61         } else {
62                 vfprintf(stderr,fmt,ap);
63                 fputc('\n',stderr); 
64         }
65         va_end(ap); 
66
67
68 int parsemac(char *str, unsigned char *mac)
69
70         char *s; 
71         while ((s = strsep(&str, ":")) != NULL) { 
72                 unsigned byte;
73                 if (sscanf(s,"%x", &byte)!=1 || byte > 0xff) 
74                         return -1;
75                 *mac++ = byte; 
76         }  
77         return 0;
78
79
80 void *xmalloc(unsigned sz)
81
82         void *p = calloc(sz,1);
83         if (!p) errno=ENOMEM, err("xmalloc"); 
84         return p; 
85
86
87 void opensock(void)
88 {
89         if (ctl_sk < 0) 
90                 ctl_sk = socket(PF_INET,SOCK_DGRAM,0); 
91 }
92
93 #ifndef ifr_newname
94 #define ifr_newname ifr_ifru.ifru_slave
95 #endif
96
97 int  setname(char *oldname, char *newname)
98 {
99         struct ifreq ifr;
100         opensock(); 
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);
105 }
106
107 int getmac(char *name, unsigned char *mac)
108 {
109         int r;
110         struct ifreq ifr;
111         opensock(); 
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); 
116         return r; 
117 }
118
119 struct change { 
120         struct change *next;
121         int found;
122         char ifname[IFNAMSIZ+1];
123         unsigned char mac[6];
124 }; 
125 struct change *clist;
126
127 struct change *lookupmac(unsigned char *mac) 
128
129         struct change *ch;
130         for (ch = clist;ch;ch = ch->next) 
131                 if (!memcmp(ch->mac, mac, 6))
132                         return ch;
133         return NULL; 
134
135
136 int addchange(char *p, struct change *ch, char *pos)
137 {
138         if (strchr(ch->ifname, ':'))
139                 warning(_("alias device %s at %s probably has no mac"), 
140                         ch->ifname, pos); 
141         if (parsemac(p,ch->mac) < 0) 
142                 complain(_("cannot parse MAC `%s' at %s"), p, pos); 
143         ch->next = clist;
144         clist = ch;
145         return 0; 
146 }
147
148 void readconf(void)
149 {
150         char *line; 
151         size_t linel; 
152         int linenum; 
153         FILE *ifh;
154         char *p;
155         int n;
156         struct change *ch = NULL;
157
158         ifh = fopen(fname, "r");
159         if (!ifh) 
160                 complain(_("opening configuration file %s: %s"),fname,strerror(errno)); 
161
162         line = NULL; 
163         linel = 0;
164         linenum = 1; 
165         while (getdelim(&line, &linel, '\n', ifh) > 0) {
166                 char pos[20]; 
167
168                 sprintf(pos, _("line %d"), linenum); 
169
170                 if ((p = strchr(line,'#')) != NULL)
171                         *p = '\0';
172                 p = line; 
173                 while (isspace(*p))
174                         ++p; 
175                 if (*p == '\0')
176                         continue; 
177                 n = strcspn(p, " \t"); 
178                 if (n > IFNAMSIZ-1) 
179                         complain(_("interface name too long at line %d"), line);  
180                 ch = xmalloc(sizeof(struct change));
181                 memcpy(ch->ifname, p, n); 
182                 ch->ifname[n] = 0; 
183                 p += n; 
184                 p += strspn(p, " \t"); 
185                 n = strspn(p, "0123456789ABCDEFabcdef:"); 
186                 p[n] = 0; 
187                 addchange(p, ch, pos);
188                 linenum++;
189         }   
190         fclose(ifh); 
191 }
192
193 struct option lopt[] = { 
194         {"syslog", 0, NULL, 's' },
195         {"config-file", 1, NULL, 'c' },
196         {"help", 0, NULL, '?' }, 
197         {NULL}, 
198 }; 
199
200 void usage(void)
201 {
202         fprintf(stderr, _("usage: nameif [-c configurationfile] [-s] {ifname macaddress}\n")); 
203         exit(1); 
204 }
205
206 int main(int ac, char **av) 
207
208         FILE *ifh; 
209         char *p;
210         int n;
211         int linenum; 
212         char *line = NULL;
213         size_t linel = 0;
214         int ret = 0;
215
216         for (;;) {
217                 int c = getopt_long(ac,av,"c:s",lopt,NULL);
218                 if (c == -1) break;
219                 switch (c) { 
220                 default:
221                 case '?':
222                         usage(); 
223                 case 'c':
224                         fname = optarg;
225                         break;
226                 case 's':
227                         use_syslog = 1;
228                         break;
229                 }
230         }
231
232         if (use_syslog) 
233                 openlog("nameif",0,LOG_LOCAL0);
234                 
235         while (optind < ac) { 
236                 struct change *ch = xmalloc(sizeof(struct change)); 
237                 char pos[30];
238
239                 if ((ac-optind) & 1) 
240                         usage();
241                 if (strlen(av[optind])+1>IFNAMSIZ) 
242                         complain(_("interface name `%s' too long"), av[optind]);
243                 strcpy(ch->ifname, av[optind]); 
244                 optind++; 
245                 sprintf(pos,_("argument %d"),optind); 
246                 addchange(av[optind], ch, pos); 
247                 optind++; 
248         } 
249
250         if (!clist || fname != default_conf) 
251                 readconf(); 
252
253         ifh = fopen("/proc/net/dev", "r"); 
254         if (!ifh)  complain(_("open of /proc/net/dev: %s"), strerror(errno)); 
255
256
257         linenum = 0;
258         while (getdelim(&line, &linel, '\n', ifh) > 0) {
259                 struct change *ch; 
260                 unsigned char mac[6];
261
262                 if (linenum++ < 2) 
263                         continue;
264                         
265                 p = line; 
266                 while (isspace(*p)) 
267                         ++p;
268                 n = strcspn(p, ": \t");  
269                 p[n] = 0; 
270                 
271                 if (n > IFNAMSIZ-1) 
272                         complain(_("interface name `%s' too long"), p); 
273                         
274                 if (getmac(p, mac) < 0) 
275                         continue;
276                         
277                 ch = lookupmac(mac); 
278                 if (!ch) 
279                         continue;
280                 
281                 ch->found = 1;  
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)); 
286                 } 
287         } 
288         fclose(ifh); 
289         
290         while (clist) { 
291                 struct change *ch = clist;
292                 clist = clist->next;
293                 if (!ch->found){
294                         warning(_("interface '%s' not found"), ch->ifname); 
295                         ret = 1;
296                 }
297                 free(ch); 
298         }
299
300         if (use_syslog)
301                 closelog();
302         return ret;
303
304