Annotation of /trunk/mkinitrd-magellan/klibc/usr/kinit/ipconfig/netdev.c
Parent Directory | Revision Log
Revision 1122 -
(hide 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)
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 | 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 | niro | 1122 | #include <linux/sockios.h> |
16 | niro | 532 | |
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 | niro | 1122 | struct sockaddr_in sin; |
45 | niro | 532 | |
46 | niro | 1122 | memset(&sin, 0, sizeof(sin)); |
47 | sin.sin_family = AF_INET; | ||
48 | sin.sin_addr.s_addr = addr; | ||
49 | niro | 532 | |
50 | niro | 1122 | memcpy(&ifr->ifr_addr, &sin, sizeof sin); |
51 | |||
52 | niro | 532 | 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 | niro | 1122 | 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 | niro | 532 | 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 | niro | 1122 | 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 | niro | 532 | 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 | } |