Commit | Line | Data |
---|---|---|
b3eab9f9 | 1 | #ifndef lint |
375a8436 | 2 | static char sccsid[] = "@(#)ifconfig.c 4.10 (Berkeley) %G%"; |
b3eab9f9 SL |
3 | #endif |
4 | ||
5 | #include <sys/types.h> | |
6 | #include <sys/socket.h> | |
7 | #include <sys/ioctl.h> | |
8 | ||
9 | #include <netinet/in.h> | |
10 | #include <net/if.h> | |
11 | ||
12 | #include <stdio.h> | |
13 | #include <errno.h> | |
14 | #include <ctype.h> | |
15 | #include <netdb.h> | |
16 | ||
17 | struct ifreq ifr; | |
18 | struct sockaddr_in sin = { AF_INET }; | |
19 | char name[30]; | |
dea973a0 | 20 | int setaddr; |
b3eab9f9 SL |
21 | int s; |
22 | ||
40a42b7f | 23 | int setifflags(), setifaddr(), setifdstaddr(); |
b3eab9f9 SL |
24 | |
25 | struct cmd { | |
26 | char *c_name; | |
27 | int c_parameter; | |
28 | int (*c_func)(); | |
29 | } cmds[] = { | |
30 | { "up", IFF_UP, setifflags } , | |
31 | { "down", -IFF_UP, setifflags }, | |
32 | { "trailers", -IFF_NOTRAILERS,setifflags }, | |
33 | { "-trailers", IFF_NOTRAILERS, setifflags }, | |
1095926d MK |
34 | { "arp", -IFF_NOARP, setifflags }, |
35 | { "-arp", IFF_NOARP, setifflags }, | |
dea973a0 MK |
36 | { "local", IFF_LOCAL, setifflags }, |
37 | { "-local", -IFF_LOCAL, setifflags }, | |
717eb130 CL |
38 | { "debug", IFF_DEBUG, setifflags }, |
39 | { "-debug", -IFF_DEBUG, setifflags }, | |
a390ced5 SL |
40 | #ifdef notdef |
41 | #define EN_SWABIPS 0x100 | |
42 | { "swabips", EN_SWABIPS, setifflags }, | |
43 | { "-swabips", -EN_SWABIPS, setifflags }, | |
44 | #endif | |
b3eab9f9 | 45 | { 0, 0, setifaddr }, |
40a42b7f | 46 | { 0, 0, setifdstaddr }, |
b3eab9f9 SL |
47 | }; |
48 | ||
49 | main(argc, argv) | |
50 | int argc; | |
51 | char *argv[]; | |
52 | { | |
53 | ||
54 | if (argc < 2) { | |
55 | fprintf(stderr, "usage: ifconfig interface %s %s %s\n", | |
40a42b7f | 56 | "[ address [ dest_addr ] ] [ up ] [ down ]", |
b3eab9f9 SL |
57 | "[ trailers | -trailers ]", |
58 | "[ arp | -arp ]"); | |
59 | exit(1); | |
60 | } | |
61 | s = socket(AF_INET, SOCK_DGRAM, 0); | |
62 | if (s < 0) { | |
63 | perror("ifconfig: socket"); | |
64 | exit(1); | |
65 | } | |
66 | argc--, argv++; | |
67 | strcpy(name, *argv); | |
68 | strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); | |
69 | if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { | |
70 | Perror("ioctl (SIOCGIFFLAGS)"); | |
71 | exit(1); | |
72 | } | |
b3eab9f9 SL |
73 | argc--, argv++; |
74 | if (argc == 0) { | |
75 | status(); | |
76 | exit(0); | |
77 | } | |
78 | while (argc > 0) { | |
79 | register struct cmd *p; | |
80 | ||
81 | for (p = cmds; p->c_name; p++) | |
82 | if (strcmp(*argv, p->c_name) == 0) | |
83 | break; | |
40a42b7f TF |
84 | if (p->c_name == 0 && setaddr) |
85 | p++; /* got src, do dst */ | |
b3eab9f9 SL |
86 | if (p->c_func) |
87 | (*p->c_func)(*argv, p->c_parameter); | |
88 | argc--, argv++; | |
89 | } | |
dea973a0 MK |
90 | if (setaddr) { |
91 | strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); | |
92 | ifr.ifr_addr = *(struct sockaddr *) &sin; | |
93 | if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) | |
94 | Perror("ioctl (SIOCSIFADDR)"); | |
95 | } | |
b3eab9f9 SL |
96 | exit(0); |
97 | } | |
98 | ||
99 | /*ARGSUSED*/ | |
100 | setifaddr(addr, param) | |
101 | char *addr; | |
102 | int param; | |
103 | { | |
104 | ||
dea973a0 MK |
105 | getaddr(addr, &sin); |
106 | /* | |
107 | * Delay the ioctl to set the interface addr until flags are all set. | |
108 | * The address interpretation may depend on the flags, | |
109 | * and the flags may change when the address is set. | |
a9575a9a | 110 | */ |
dea973a0 | 111 | setaddr++; |
b3eab9f9 SL |
112 | } |
113 | ||
40a42b7f TF |
114 | /*ARGSUSED*/ |
115 | setifdstaddr(addr, param) | |
116 | char *addr; | |
117 | int param; | |
118 | { | |
375a8436 | 119 | int flags = ifr.ifr_flags; |
40a42b7f TF |
120 | |
121 | getaddr(addr, (struct sockaddr_in *)&ifr.ifr_dstaddr); | |
122 | strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); | |
123 | if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) | |
124 | Perror("ioctl (SIOCSIFDSTADDR)"); | |
375a8436 | 125 | ifr.ifr_flags = flags; |
40a42b7f TF |
126 | } |
127 | ||
2c4ef00e SL |
128 | setifflags(vname, value) |
129 | char *vname; | |
b3eab9f9 SL |
130 | int value; |
131 | { | |
132 | ||
133 | if (value < 0) { | |
134 | value = -value; | |
dea973a0 | 135 | ifr.ifr_flags &= ~value; |
b3eab9f9 | 136 | } else |
dea973a0 | 137 | ifr.ifr_flags |= value; |
b3eab9f9 SL |
138 | strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); |
139 | if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) | |
2c4ef00e | 140 | Perror(vname); |
b3eab9f9 SL |
141 | } |
142 | ||
143 | status() | |
144 | { | |
145 | struct sockaddr_in *sin; | |
dea973a0 | 146 | int flags = ifr.ifr_flags; |
b3eab9f9 SL |
147 | |
148 | strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); | |
149 | if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) | |
150 | Perror("ioctl (SIOCGIFADDR)"); | |
151 | sin = (struct sockaddr_in *)&ifr.ifr_addr; | |
152 | printf("%s: %s ", name, inet_ntoa(sin->sin_addr)); | |
40a42b7f TF |
153 | if (flags & IFF_POINTOPOINT) { |
154 | strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); | |
155 | if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) | |
156 | Perror("ioctl (SIOCGIFDSTADDR)"); | |
157 | sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; | |
158 | printf("--> %s ", inet_ntoa(sin->sin_addr)); | |
159 | } | |
b3eab9f9 | 160 | #define IFFBITS \ |
dea973a0 MK |
161 | "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ |
162 | \11LOCAL" | |
b3eab9f9 SL |
163 | printb("flags", flags, IFFBITS); putchar('\n'); |
164 | } | |
165 | ||
166 | Perror(cmd) | |
167 | char *cmd; | |
168 | { | |
169 | extern int errno; | |
170 | ||
171 | fprintf(stderr, "ifconfig: "); | |
172 | switch (errno) { | |
173 | ||
174 | case ENXIO: | |
175 | fprintf(stderr, "%s: ", cmd); | |
176 | fprintf(stderr, "no such interface\n"); | |
177 | break; | |
178 | ||
179 | case EPERM: | |
9f1b5d96 | 180 | fprintf(stderr, "%s: permission denied\n", cmd); |
b3eab9f9 SL |
181 | break; |
182 | ||
183 | default: | |
184 | perror(cmd); | |
185 | } | |
186 | exit(1); | |
187 | } | |
188 | ||
189 | struct in_addr inet_makeaddr(); | |
190 | ||
191 | getaddr(s, sin) | |
192 | char *s; | |
193 | struct sockaddr_in *sin; | |
194 | { | |
195 | struct hostent *hp; | |
196 | struct netent *np; | |
197 | int val; | |
198 | ||
199 | hp = gethostbyname(s); | |
200 | if (hp) { | |
201 | sin->sin_family = hp->h_addrtype; | |
202 | bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); | |
203 | return; | |
204 | } | |
205 | np = getnetbyname(s); | |
206 | if (np) { | |
207 | sin->sin_family = np->n_addrtype; | |
208 | sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); | |
209 | return; | |
210 | } | |
211 | sin->sin_family = AF_INET; | |
212 | val = inet_addr(s); | |
213 | if (val != -1) { | |
214 | sin->sin_addr.s_addr = val; | |
215 | return; | |
216 | } | |
217 | val = inet_network(s); | |
218 | if (val != -1) { | |
219 | sin->sin_addr = inet_makeaddr(val, INADDR_ANY); | |
220 | return; | |
221 | } | |
222 | fprintf(stderr, "%s: bad value\n", s); | |
223 | exit(1); | |
224 | } | |
225 | ||
226 | /* | |
227 | * Print a value a la the %b format of the kernel's printf | |
228 | */ | |
229 | printb(s, v, bits) | |
230 | char *s; | |
231 | register char *bits; | |
232 | register unsigned short v; | |
233 | { | |
234 | register int i, any = 0; | |
235 | register char c; | |
236 | ||
237 | if (bits && *bits == 8) | |
238 | printf("%s=%o", s, v); | |
239 | else | |
240 | printf("%s=%x", s, v); | |
241 | bits++; | |
242 | if (bits) { | |
243 | putchar('<'); | |
244 | while (i = *bits++) { | |
245 | if (v & (1 << (i-1))) { | |
246 | if (any) | |
247 | putchar(','); | |
248 | any = 1; | |
249 | for (; (c = *bits) > 32; bits++) | |
250 | putchar(c); | |
251 | } else | |
252 | for (; *bits > 32; bits++) | |
253 | ; | |
254 | } | |
255 | putchar('>'); | |
256 | } | |
257 | } |