Annotation of /trunk/mkinitrd-magellan/klibc/usr/kinit/ipconfig/netdev.c
Parent Directory | Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 5094 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 5094 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | niro | 532 | /* |
2 | * ioctl-based device configuration | ||
3 | */ | ||
4 | #include <sys/types.h> | ||
5 | #include <sys/socket.h> | ||
6 | #include <sys/ioctl.h> | ||
7 | #include <errno.h> | ||
8 | #include <stdio.h> | ||
9 | #include <string.h> | ||
10 | #include <unistd.h> | ||
11 | #include <net/if.h> | ||
12 | #include <net/if_arp.h> | ||
13 | #include <netinet/in.h> | ||
14 | #include <linux/route.h> | ||
15 | |||
16 | #include "netdev.h" | ||
17 | |||
18 | static int cfd = -1; | ||
19 | |||
20 | static void copy_name(struct netdev *dev, struct ifreq *ifr) | ||
21 | { | ||
22 | strncpy(ifr->ifr_name, dev->name, sizeof(ifr->ifr_name)); | ||
23 | ifr->ifr_name[sizeof(ifr->ifr_name) - 1] = '\0'; | ||
24 | } | ||
25 | |||
26 | int netdev_getflags(struct netdev *dev, short *flags) | ||
27 | { | ||
28 | struct ifreq ifr; | ||
29 | |||
30 | copy_name(dev, &ifr); | ||
31 | |||
32 | if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) { | ||
33 | perror("SIOCGIFFLAGS"); | ||
34 | return -1; | ||
35 | } | ||
36 | |||
37 | *flags = ifr.ifr_flags; | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static int netdev_sif_addr(struct ifreq *ifr, int cmd, uint32_t addr) | ||
42 | { | ||
43 | struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr; | ||
44 | |||
45 | sin->sin_family = AF_INET; | ||
46 | sin->sin_addr.s_addr = addr; | ||
47 | |||
48 | return ioctl(cfd, cmd, ifr); | ||
49 | } | ||
50 | |||
51 | int netdev_setaddress(struct netdev *dev) | ||
52 | { | ||
53 | struct ifreq ifr; | ||
54 | |||
55 | copy_name(dev, &ifr); | ||
56 | |||
57 | if (dev->ip_addr != INADDR_ANY && | ||
58 | netdev_sif_addr(&ifr, SIOCSIFADDR, dev->ip_addr) == -1) { | ||
59 | perror("SIOCSIFADDR"); | ||
60 | return -1; | ||
61 | } | ||
62 | |||
63 | if (dev->ip_broadcast != INADDR_ANY && | ||
64 | netdev_sif_addr(&ifr, SIOCSIFBRDADDR, dev->ip_broadcast) == -1) { | ||
65 | perror("SIOCSIFBRDADDR"); | ||
66 | return -1; | ||
67 | } | ||
68 | |||
69 | if (dev->ip_netmask != INADDR_ANY && | ||
70 | netdev_sif_addr(&ifr, SIOCSIFNETMASK, dev->ip_netmask) == -1) { | ||
71 | perror("SIOCSIFNETMASK"); | ||
72 | return -1; | ||
73 | } | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | int netdev_setdefaultroute(struct netdev *dev) | ||
79 | { | ||
80 | struct rtentry r; | ||
81 | |||
82 | if (dev->ip_gateway == INADDR_ANY) | ||
83 | return 0; | ||
84 | |||
85 | memset(&r, 0, sizeof(r)); | ||
86 | |||
87 | ((struct sockaddr_in *)&r.rt_dst)->sin_family = AF_INET; | ||
88 | ((struct sockaddr_in *)&r.rt_dst)->sin_addr.s_addr = INADDR_ANY; | ||
89 | ((struct sockaddr_in *)&r.rt_gateway)->sin_family = AF_INET; | ||
90 | ((struct sockaddr_in *)&r.rt_gateway)->sin_addr.s_addr = | ||
91 | dev->ip_gateway; | ||
92 | ((struct sockaddr_in *)&r.rt_genmask)->sin_family = AF_INET; | ||
93 | ((struct sockaddr_in *)&r.rt_genmask)->sin_addr.s_addr = INADDR_ANY; | ||
94 | r.rt_flags = RTF_UP | RTF_GATEWAY; | ||
95 | |||
96 | if (ioctl(cfd, SIOCADDRT, &r) == -1 && errno != EEXIST) { | ||
97 | perror("SIOCADDRT"); | ||
98 | return -1; | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int netdev_setmtu(struct netdev *dev) | ||
104 | { | ||
105 | struct ifreq ifr; | ||
106 | |||
107 | copy_name(dev, &ifr); | ||
108 | ifr.ifr_mtu = dev->mtu; | ||
109 | |||
110 | return ioctl(cfd, SIOCSIFMTU, &ifr); | ||
111 | } | ||
112 | |||
113 | static int netdev_gif_addr(struct ifreq *ifr, int cmd, uint32_t * ptr) | ||
114 | { | ||
115 | struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr; | ||
116 | |||
117 | if (ioctl(cfd, cmd, ifr) == -1) | ||
118 | return -1; | ||
119 | |||
120 | *ptr = sin->sin_addr.s_addr; | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | int netdev_up(struct netdev *dev) | ||
126 | { | ||
127 | struct ifreq ifr; | ||
128 | |||
129 | copy_name(dev, &ifr); | ||
130 | |||
131 | if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) { | ||
132 | perror("SIOCGIFFLAGS"); | ||
133 | return -1; | ||
134 | } | ||
135 | |||
136 | ifr.ifr_flags |= IFF_UP; | ||
137 | |||
138 | if (ioctl(cfd, SIOCSIFFLAGS, &ifr) == -1) { | ||
139 | perror("SIOCSIFFLAGS"); | ||
140 | return -1; | ||
141 | } | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | int netdev_down(struct netdev *dev) | ||
146 | { | ||
147 | struct ifreq ifr; | ||
148 | |||
149 | copy_name(dev, &ifr); | ||
150 | |||
151 | if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) { | ||
152 | perror("SIOCGIFFLAGS"); | ||
153 | return -1; | ||
154 | } | ||
155 | |||
156 | ifr.ifr_flags &= ~IFF_UP; | ||
157 | |||
158 | if (ioctl(cfd, SIOCSIFFLAGS, &ifr) == -1) { | ||
159 | perror("SIOCSIFFLAGS"); | ||
160 | return -1; | ||
161 | } | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | int netdev_init_if(struct netdev *dev) | ||
166 | { | ||
167 | struct ifreq ifr; | ||
168 | |||
169 | if (cfd == -1) | ||
170 | cfd = socket(AF_INET, SOCK_DGRAM, 0); | ||
171 | if (cfd == -1) { | ||
172 | fprintf(stderr, "ipconfig: %s: socket(AF_INET): %s\n", | ||
173 | dev->name, strerror(errno)); | ||
174 | return -1; | ||
175 | } | ||
176 | |||
177 | copy_name(dev, &ifr); | ||
178 | |||
179 | if (ioctl(cfd, SIOCGIFINDEX, &ifr) == -1) { | ||
180 | fprintf(stderr, "ipconfig: %s: SIOCGIFINDEX: %s\n", | ||
181 | dev->name, strerror(errno)); | ||
182 | return -1; | ||
183 | } | ||
184 | |||
185 | dev->ifindex = ifr.ifr_ifindex; | ||
186 | |||
187 | if (ioctl(cfd, SIOCGIFMTU, &ifr) == -1) { | ||
188 | fprintf(stderr, "ipconfig: %s: SIOCGIFMTU: %s\n", | ||
189 | dev->name, strerror(errno)); | ||
190 | return -1; | ||
191 | } | ||
192 | |||
193 | dev->mtu = ifr.ifr_mtu; | ||
194 | |||
195 | if (ioctl(cfd, SIOCGIFHWADDR, &ifr) == -1) { | ||
196 | fprintf(stderr, "ipconfig: %s: SIOCGIFHWADDR: %s\n", | ||
197 | dev->name, strerror(errno)); | ||
198 | return -1; | ||
199 | } | ||
200 | |||
201 | dev->hwtype = ifr.ifr_hwaddr.sa_family; | ||
202 | dev->hwlen = 0; | ||
203 | |||
204 | switch (dev->hwtype) { | ||
205 | case ARPHRD_ETHER: | ||
206 | dev->hwlen = 6; | ||
207 | break; | ||
208 | case ARPHRD_EUI64: | ||
209 | dev->hwlen = 8; | ||
210 | break; | ||
211 | case ARPHRD_LOOPBACK: | ||
212 | dev->hwlen = 0; | ||
213 | break; | ||
214 | default: | ||
215 | return -1; | ||
216 | } | ||
217 | |||
218 | memcpy(dev->hwaddr, ifr.ifr_hwaddr.sa_data, dev->hwlen); | ||
219 | memset(dev->hwbrd, 0xff, dev->hwlen); | ||
220 | |||
221 | /* | ||
222 | * Try to get the current interface information. | ||
223 | */ | ||
224 | if (dev->ip_addr == INADDR_NONE && | ||
225 | netdev_gif_addr(&ifr, SIOCGIFADDR, &dev->ip_addr) == -1) { | ||
226 | fprintf(stderr, "ipconfig: %s: SIOCGIFADDR: %s\n", | ||
227 | dev->name, strerror(errno)); | ||
228 | dev->ip_addr = 0; | ||
229 | dev->ip_broadcast = 0; | ||
230 | dev->ip_netmask = 0; | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | if (dev->ip_broadcast == INADDR_NONE && | ||
235 | netdev_gif_addr(&ifr, SIOCGIFBRDADDR, &dev->ip_broadcast) == -1) { | ||
236 | fprintf(stderr, "ipconfig: %s: SIOCGIFBRDADDR: %s\n", | ||
237 | dev->name, strerror(errno)); | ||
238 | dev->ip_broadcast = 0; | ||
239 | } | ||
240 | |||
241 | if (dev->ip_netmask == INADDR_NONE && | ||
242 | netdev_gif_addr(&ifr, SIOCGIFNETMASK, &dev->ip_netmask) == -1) { | ||
243 | fprintf(stderr, "ipconfig: %s: SIOCGIFNETMASK: %s\n", | ||
244 | dev->name, strerror(errno)); | ||
245 | dev->ip_netmask = 0; | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | } |