Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/kinit/ipconfig/netdev.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 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 /*
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 }