Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/networking/libiproute/iplink.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 6572 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * iplink.c "ip link".
4     *
5     * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
6     *
7     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8     */
9    
10 niro 816 //#include <sys/ioctl.h>
11     //#include <sys/socket.h>
12 niro 532 #include <net/if.h>
13     #include <net/if_packet.h>
14     #include <netpacket/packet.h>
15     #include <net/ethernet.h>
16    
17 niro 816 #include "ip_common.h" /* #include "libbb.h" is inside */
18 niro 532 #include "rt_names.h"
19     #include "utils.h"
20    
21 niro 816 /* taken from linux/sockios.h */
22 niro 532 #define SIOCSIFNAME 0x8923 /* set interface name */
23    
24 niro 816 /* Exits on error */
25 niro 532 static int get_ctl_fd(void)
26     {
27     int fd;
28    
29     fd = socket(PF_INET, SOCK_DGRAM, 0);
30     if (fd >= 0)
31     return fd;
32     fd = socket(PF_PACKET, SOCK_DGRAM, 0);
33     if (fd >= 0)
34     return fd;
35 niro 816 return xsocket(PF_INET6, SOCK_DGRAM, 0);
36 niro 532 }
37    
38 niro 816 /* Exits on error */
39     static void do_chflags(char *dev, uint32_t flags, uint32_t mask)
40 niro 532 {
41     struct ifreq ifr;
42     int fd;
43    
44 niro 984 strncpy_IFNAMSIZ(ifr.ifr_name, dev);
45 niro 532 fd = get_ctl_fd();
46 niro 816 xioctl(fd, SIOCGIFFLAGS, &ifr);
47     if ((ifr.ifr_flags ^ flags) & mask) {
48 niro 532 ifr.ifr_flags &= ~mask;
49 niro 816 ifr.ifr_flags |= mask & flags;
50     xioctl(fd, SIOCSIFFLAGS, &ifr);
51 niro 532 }
52     close(fd);
53     }
54    
55 niro 816 /* Exits on error */
56     static void do_changename(char *dev, char *newdev)
57 niro 532 {
58     struct ifreq ifr;
59     int fd;
60    
61 niro 984 strncpy_IFNAMSIZ(ifr.ifr_name, dev);
62     strncpy_IFNAMSIZ(ifr.ifr_newname, newdev);
63 niro 532 fd = get_ctl_fd();
64 niro 816 xioctl(fd, SIOCSIFNAME, &ifr);
65 niro 532 close(fd);
66     }
67    
68 niro 816 /* Exits on error */
69     static void set_qlen(char *dev, int qlen)
70 niro 532 {
71     struct ifreq ifr;
72     int s;
73    
74     s = get_ctl_fd();
75     memset(&ifr, 0, sizeof(ifr));
76 niro 984 strncpy_IFNAMSIZ(ifr.ifr_name, dev);
77 niro 532 ifr.ifr_qlen = qlen;
78 niro 816 xioctl(s, SIOCSIFTXQLEN, &ifr);
79 niro 532 close(s);
80     }
81    
82 niro 816 /* Exits on error */
83     static void set_mtu(char *dev, int mtu)
84 niro 532 {
85     struct ifreq ifr;
86     int s;
87    
88     s = get_ctl_fd();
89     memset(&ifr, 0, sizeof(ifr));
90 niro 984 strncpy_IFNAMSIZ(ifr.ifr_name, dev);
91 niro 532 ifr.ifr_mtu = mtu;
92 niro 816 xioctl(s, SIOCSIFMTU, &ifr);
93 niro 532 close(s);
94     }
95    
96 niro 816 /* Exits on error */
97 niro 532 static int get_address(char *dev, int *htype)
98     {
99     struct ifreq ifr;
100     struct sockaddr_ll me;
101     socklen_t alen;
102     int s;
103    
104 niro 816 s = xsocket(PF_PACKET, SOCK_DGRAM, 0);
105 niro 532
106     memset(&ifr, 0, sizeof(ifr));
107 niro 984 strncpy_IFNAMSIZ(ifr.ifr_name, dev);
108 niro 816 xioctl(s, SIOCGIFINDEX, &ifr);
109 niro 532
110     memset(&me, 0, sizeof(me));
111     me.sll_family = AF_PACKET;
112     me.sll_ifindex = ifr.ifr_ifindex;
113     me.sll_protocol = htons(ETH_P_LOOP);
114 niro 816 xbind(s, (struct sockaddr*)&me, sizeof(me));
115 niro 532 alen = sizeof(me);
116 niro 984 getsockname(s, (struct sockaddr*)&me, &alen);
117     //never happens:
118     //if (getsockname(s, (struct sockaddr*)&me, &alen) == -1)
119     // bb_perror_msg_and_die("getsockname");
120 niro 532 close(s);
121     *htype = me.sll_hatype;
122     return me.sll_halen;
123     }
124    
125 niro 816 /* Exits on error */
126     static void parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr)
127 niro 532 {
128     int alen;
129    
130     memset(ifr, 0, sizeof(*ifr));
131 niro 984 strncpy_IFNAMSIZ(ifr->ifr_name, dev);
132 niro 532 ifr->ifr_hwaddr.sa_family = hatype;
133 niro 816
134     alen = hatype == 1/*ARPHRD_ETHER*/ ? 14/*ETH_HLEN*/ : 19/*INFINIBAND_HLEN*/;
135     alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), alen, lla);
136 niro 532 if (alen < 0)
137 niro 816 exit(EXIT_FAILURE);
138 niro 532 if (alen != halen) {
139 niro 816 bb_error_msg_and_die("wrong address (%s) length: expected %d bytes", lla, halen);
140 niro 532 }
141     }
142    
143 niro 816 /* Exits on error */
144     static void set_address(struct ifreq *ifr, int brd)
145 niro 532 {
146     int s;
147    
148     s = get_ctl_fd();
149 niro 816 if (brd)
150     xioctl(s, SIOCSIFHWBROADCAST, ifr);
151     else
152     xioctl(s, SIOCSIFHWADDR, ifr);
153 niro 532 close(s);
154     }
155    
156    
157 niro 816 static void die_must_be_on_off(const char *msg) NORETURN;
158     static void die_must_be_on_off(const char *msg)
159 niro 532 {
160 niro 816 bb_error_msg_and_die("argument of \"%s\" must be \"on\" or \"off\"", msg);
161     }
162    
163     /* Return value becomes exitcode. It's okay to not return at all */
164     static int do_set(char **argv)
165     {
166 niro 532 char *dev = NULL;
167     uint32_t mask = 0;
168     uint32_t flags = 0;
169     int qlen = -1;
170     int mtu = -1;
171     char *newaddr = NULL;
172     char *newbrd = NULL;
173     struct ifreq ifr0, ifr1;
174     char *newname = NULL;
175     int htype, halen;
176 niro 816 static const char keywords[] ALIGN1 =
177     "up\0""down\0""name\0""mtu\0""multicast\0"
178     "arp\0""address\0""dev\0";
179     enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_multicast,
180     ARG_arp, ARG_addr, ARG_dev };
181     static const char str_on_off[] ALIGN1 = "on\0""off\0";
182     enum { PARM_on = 0, PARM_off };
183     smalluint key;
184 niro 532
185 niro 816 while (*argv) {
186     /* substring search ensures that e.g. "addr" and "address"
187     * are both accepted */
188     key = index_in_substrings(keywords, *argv);
189     if (key == ARG_up) {
190 niro 532 mask |= IFF_UP;
191     flags |= IFF_UP;
192 niro 816 }
193     if (key == ARG_down) {
194 niro 532 mask |= IFF_UP;
195     flags &= ~IFF_UP;
196 niro 816 }
197     if (key == ARG_name) {
198 niro 532 NEXT_ARG();
199     newname = *argv;
200 niro 816 }
201     if (key == ARG_mtu) {
202 niro 532 NEXT_ARG();
203     if (mtu != -1)
204     duparg("mtu", *argv);
205 niro 984 mtu = get_unsigned(*argv, "mtu");
206 niro 816 }
207     if (key == ARG_multicast) {
208     int param;
209 niro 532 NEXT_ARG();
210     mask |= IFF_MULTICAST;
211 niro 816 param = index_in_strings(str_on_off, *argv);
212     if (param < 0)
213     die_must_be_on_off("multicast");
214     if (param == PARM_on)
215 niro 532 flags |= IFF_MULTICAST;
216 niro 816 else
217 niro 532 flags &= ~IFF_MULTICAST;
218 niro 816 }
219     if (key == ARG_arp) {
220     int param;
221 niro 532 NEXT_ARG();
222     mask |= IFF_NOARP;
223 niro 816 param = index_in_strings(str_on_off, *argv);
224     if (param < 0)
225     die_must_be_on_off("arp");
226     if (param == PARM_on)
227 niro 532 flags &= ~IFF_NOARP;
228 niro 816 else
229 niro 532 flags |= IFF_NOARP;
230 niro 816 }
231     if (key == ARG_addr) {
232 niro 532 NEXT_ARG();
233     newaddr = *argv;
234 niro 816 }
235     if (key >= ARG_dev) {
236     if (key == ARG_dev) {
237 niro 532 NEXT_ARG();
238     }
239     if (dev)
240     duparg2("dev", *argv);
241     dev = *argv;
242     }
243 niro 816 argv++;
244 niro 532 }
245    
246     if (!dev) {
247 niro 816 bb_error_msg_and_die(bb_msg_requires_arg, "\"dev\"");
248 niro 532 }
249    
250     if (newaddr || newbrd) {
251     halen = get_address(dev, &htype);
252     if (newaddr) {
253 niro 816 parse_address(dev, htype, halen, newaddr, &ifr0);
254 niro 532 }
255     if (newbrd) {
256 niro 816 parse_address(dev, htype, halen, newbrd, &ifr1);
257 niro 532 }
258     }
259    
260     if (newname && strcmp(dev, newname)) {
261 niro 816 do_changename(dev, newname);
262 niro 532 dev = newname;
263     }
264     if (qlen != -1) {
265 niro 816 set_qlen(dev, qlen);
266 niro 532 }
267     if (mtu != -1) {
268 niro 816 set_mtu(dev, mtu);
269 niro 532 }
270     if (newaddr || newbrd) {
271     if (newbrd) {
272 niro 816 set_address(&ifr1, 1);
273 niro 532 }
274     if (newaddr) {
275 niro 816 set_address(&ifr0, 0);
276 niro 532 }
277     }
278     if (mask)
279 niro 816 do_chflags(dev, flags, mask);
280 niro 532 return 0;
281     }
282    
283 niro 816 static int ipaddr_list_link(char **argv)
284 niro 532 {
285     preferred_family = AF_PACKET;
286 niro 816 return ipaddr_list_or_flush(argv, 0);
287 niro 532 }
288    
289 niro 816 /* Return value becomes exitcode. It's okay to not return at all */
290     int do_iplink(char **argv)
291 niro 532 {
292 niro 816 static const char keywords[] ALIGN1 =
293     "set\0""show\0""lst\0""list\0";
294     int key;
295     if (!*argv)
296     return ipaddr_list_link(argv);
297     key = index_in_substrings(keywords, *argv);
298     if (key < 0)
299     bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
300     argv++;
301     if (key == 0) /* set */
302     return do_set(argv);
303     /* show, lst, list */
304     return ipaddr_list_link(argv);
305 niro 532 }