Contents of /trunk/mkinitrd-magellan/klibc/usr/kinit/ipconfig/netdev.c
Parent Directory | Revision Log
Revision 1122 -
(show annotations)
(download)
Wed Aug 18 21:11:40 2010 UTC (13 years, 9 months ago) by niro
File MIME type: text/plain
File size: 5066 byte(s)
Wed Aug 18 21:11:40 2010 UTC (13 years, 9 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 | } |