Magellan Linux

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

Parent Directory Parent Directory | Revision Log 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)
-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     }