Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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