source: projects/initscripts/tags/initscripts-8.91.3/src/rename_device.c @ 1108

Revision 1108, 7.4 KB checked in by daisuke, 14 years ago (diff)

import initscripts-8.90.6 from internal cvs repository

Line 
1
2/*
3 * rename_device.c: udev helper to rename ethernet devices.
4 *
5 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
6 *
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions of the
9 * GNU General Public License v.2.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21
22#include <dirent.h>
23#include <errno.h>
24#include <fcntl.h>
25#include <signal.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
31#include <sys/ioctl.h>
32#include <sys/time.h>
33#include <sys/types.h>
34
35#include <linux/sockios.h>
36
37#include <net/if.h>
38
39#include <glib.h>
40
41#define LOCKFILE "/dev/.rename_device.lock"
42
43void sighandler(int dummy) {
44        unlink(LOCKFILE);
45        _exit(1);
46}
47
48struct netdev {
49        char *hwaddr;
50        char *dev;
51        struct netdev *next;
52};
53
54struct tmp {
55        char *src;
56        char *target;
57        struct tmp *next;
58};
59
60struct netdev *configs = NULL;
61struct netdev *devs = NULL;
62struct tmp *tmplist = NULL;
63
64#if defined(__s390__) || defined(__s390x__)
65static int is_cdev(const struct dirent *dent) {
66        char *end = NULL;
67       
68        if (strncmp(dent->d_name,"cdev",4))
69                return 0;
70        strtoul(dent->d_name+4,&end, 10);
71        if (*end)
72                return 0;
73        return 1;
74}
75
76static inline char *getdev(char *path, char *ent) {
77        char *a, *b, *ret;
78       
79        asprintf(&a,"%s/%s",path,ent);
80        b = canonicalize_file_name(a);
81        ret = strdup(basename(b));
82        free(b);
83        free(a);
84        return ret;
85}
86
87char *read_subchannels(char *device) {
88        char *tmp, *path, *ret;
89        int n, x;
90        struct dirent **cdevs;
91               
92        if (asprintf(&path,"/sys/class/net/%s/device",device) == -1)
93                return NULL;
94        if ((n = scandir(path, &cdevs, is_cdev, alphasort)) <= 0)
95                return NULL;
96               
97        ret = getdev(path,cdevs[0]->d_name);
98        for (x = 1 ; x < n ; x++ ) { 
99                if (asprintf(&tmp, "%s,%s", ret, getdev(path, cdevs[x]->d_name)) == -1) 
100                        return NULL;
101                free(ret);
102                ret = tmp;
103        }
104        free(path);
105        return ret;
106}
107
108#endif
109
110struct netdev *get_devs() {
111        DIR *dir;
112        struct dirent *entry;
113        struct netdev *ret = NULL, *tmpdev;
114       
115        dir = opendir("/sys/class/net");
116        if (!dir)
117                return NULL;
118        while ((entry = readdir(dir))) {
119                char *path;
120                gchar *contents;
121               
122                contents = NULL;
123               
124                if (!strcmp(entry->d_name,".") || !strcmp(entry->d_name,"..")) {
125                        continue;
126                }
127                if (asprintf(&path,"/sys/class/net/%s/type",entry->d_name) == -1)
128                        continue;
129                g_file_get_contents(path, &contents, NULL, NULL);
130                if (!contents) continue;
131                if (atoi(contents) >= 256) {
132                        g_free(contents);
133                        continue;
134                }
135                g_free(contents);
136                contents = NULL;
137#if defined(__s390__) || defined(__s390x__)
138                contents = read_subchannels(entry->d_name);
139#else
140                if (asprintf(&path,"/sys/class/net/%s/address",entry->d_name) == -1)
141                        continue;
142                g_file_get_contents(path, &contents, NULL, NULL);
143#endif /* mainframe */
144                if (!contents) continue;
145                contents = g_strstrip(contents);
146                tmpdev = calloc(1, sizeof(struct netdev));
147                tmpdev->dev = g_strstrip(g_strdup(entry->d_name));
148                tmpdev->hwaddr = g_strstrip(g_strdup(contents));
149                if (ret)
150                        tmpdev->next = ret;
151                ret = tmpdev;
152                g_free(contents);
153        }
154        return ret;
155}
156
157int isCfg(const struct dirent *dent) {
158        int len = strlen(dent->d_name);
159       
160        if (strncmp(dent->d_name,"ifcfg-",6))
161                return 0;
162        if (strstr(dent->d_name,"rpmnew") ||
163            strstr(dent->d_name,"rpmsave") ||
164            strstr(dent->d_name,"rpmorig"))
165                return 0;
166        if (dent->d_name[len-1] == '~')
167                return 0;
168        if (!strncmp(dent->d_name+len-4,".bak",4))
169                return 0;
170        return 1;
171}
172
173static inline char *dequote(char *start, char *end) {
174        if (end==NULL) {
175                end=start;
176                while(*end) end++;
177        }
178        if (end > start) end--;
179        if ((*start == '\'' || *start == '\"') && ( *start == *end ) ) {
180                *end='\0';
181                if (start<end) start++;
182        }
183        return start;
184}
185
186struct netdev *get_configs() {
187        int ncfgs = 0;
188        struct netdev *ret, *tmpdev;
189        struct dirent **cfgs;
190        int x;
191       
192        ret = NULL;
193       
194        if ((ncfgs = scandir("/etc/sysconfig/network-scripts",&cfgs,
195                             isCfg, alphasort)) == -1) {
196                return ret;
197        }
198        for (x = 0; x < ncfgs; x++ ) {
199                char *path;
200                char *devname, *hwaddr;
201                gchar *contents, **lines;
202                int i;
203               
204                devname = hwaddr = contents = NULL;
205                lines = NULL;
206                if (asprintf(&path,"/etc/sysconfig/network-scripts/%s",
207                             cfgs[x]->d_name) == -1)
208                        continue;
209                g_file_get_contents(path, &contents, NULL, NULL);
210                if (!contents)
211                        continue;
212                lines = g_strsplit(contents,"\n", 0);
213                for (i = 0; lines[i]; i++) {
214                        if (g_str_has_prefix(lines[i],"DEVICE=")) {
215                                devname = lines[i] + 7;
216                                /* ignore alias devices */
217                                if (strchr(devname,':'))
218                                        devname = NULL;
219                        }
220#if defined(__s390__) || defined(__s390x__)
221                        if (g_str_has_prefix(lines[i],"SUBCHANNELS=")) {
222                                hwaddr = dequote(lines[i] + 12, NULL);
223                        }
224#else
225                        if (g_str_has_prefix(lines[i],"HWADDR=")) {
226                                hwaddr = dequote(lines[i] + 7, NULL);
227                        }
228#endif
229                }
230                if (!devname || !hwaddr) {
231                        g_free(contents);
232                        g_strfreev(lines);
233                        continue;
234                }
235                tmpdev = calloc(1, sizeof(struct netdev));
236                tmpdev->dev = g_strstrip(g_strdup(devname));
237                tmpdev->hwaddr = g_strstrip(g_strdup(hwaddr));
238                if (ret)
239                        tmpdev->next = ret;
240                ret = tmpdev;
241                g_free(contents);
242                g_strfreev(lines);
243        }
244        free(cfgs);
245        return ret;
246}
247               
248char *get_hwaddr(char *device) {
249        struct netdev *dev;
250       
251        for (dev = devs; dev; dev = dev->next)
252                if (!strcmp(dev->dev, device))
253                        return dev->hwaddr;
254        return NULL;
255}
256               
257char *get_config_by_hwaddr(char *hwaddr, char *current) {
258        struct netdev *config;
259        char *first = NULL;
260       
261        if (!hwaddr) return NULL;
262       
263        for (config = configs; config; config = config->next) {
264                if (strcasecmp(config->hwaddr, hwaddr) != 0)
265                        continue;
266                if (!current || !strcasecmp(config->dev, current))
267                        return config->dev;
268                if (!first)
269                        first = config->dev;
270        }
271        return first;
272}
273
274char *get_device_by_hwaddr(char *hwaddr) {
275        struct netdev *dev;
276       
277        if (!hwaddr) return NULL;
278       
279        for (dev = devs; dev; dev = dev->next)
280                if (!strcasecmp(dev->hwaddr, hwaddr))
281                        return dev->dev;
282        return NULL;
283}
284
285void take_lock() {
286        int count = 0;
287        int lockfd;
288       
289        while (1) {
290                lockfd = open(LOCKFILE, O_RDWR|O_CREAT|O_EXCL, 0644);
291                if (lockfd != -1) {
292                        write(lockfd,"%d\n",getpid());
293                        close(lockfd);
294                        break;
295                }
296                count++;
297                /* If we've slept for 20 seconds, break the lock. */
298                if (count >= 200) {
299                        int fd;
300                        char buf[32];
301                        int pid;
302                               
303                        fd = open(LOCKFILE, O_RDONLY);
304                        if (fd == -1)
305                                break;
306                        read(fd,buf,32);
307                        close(fd);
308                        pid = atoi(buf);
309                        if (pid && pid != 1) {
310                                kill(pid,SIGKILL);
311                        }
312                }
313                usleep(100000);
314                continue;
315
316        }
317        return;
318}
319
320int main(int argc, char **argv) {
321        char *src, *target, *hw;
322        struct timeval tv;
323
324        gettimeofday(&tv, NULL);
325        srand(tv.tv_usec);     
326        take_lock();
327       
328        signal(SIGSEGV,sighandler);
329        signal(SIGKILL,sighandler);
330        signal(SIGTERM,sighandler);
331        signal(SIGSEGV,sighandler);
332        signal(SIGALRM,sighandler);
333        alarm(10);
334       
335        configs = get_configs();
336        devs = get_devs();
337       
338        src = getenv("INTERFACE");
339        if (!src)
340                goto out_unlock;
341        hw = get_hwaddr(src);
342        if (!hw)
343                goto out_unlock;
344        target = get_config_by_hwaddr(hw, src);
345        if (!target)
346                goto out_unlock;
347
348        printf("%s", target);
349       
350out_unlock:
351        unlink(LOCKFILE);
352        exit(0);
353}
Note: See TracBrowser for help on using the repository browser.