2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
17 #include <sys/param.h>
21 #include <sys/ioctl.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
36 struct intf addrs[MAX_INTF];
42 #include "AFS_component_version_number.c"
49 syslog(LOG_ERR, "ifconfig test");
50 create_sockets(htons(43242));
51 for (i = 0; i < nintf; i++) {
52 printf("%d: %s fd %d addr %s mask %x ", i, addrs[i].name,
53 addrs[i].fd, inet_ntoa(addrs[i].sin.sin_addr.s_addr),
54 ntohl(addrs[i].mask.sin_addr.s_addr));
57 (addrs[0].fd, SOL_SOCKET, SO_BROADCAST, (char *)&val, &cc)) {
61 printf("BCAST opt %d", val);
63 if (getsockopt(addrs[0].fd, SOL_SOCKET, SO_RCVBUF, (char *)&val, &cc)) {
67 printf("sockbuf size = %d ", val);
71 for (i = 0; i < nintf; i++) {
72 fprintf(stderr, "Read fd %d.. ", addrs[i].fd);
73 cc = read(addrs[i].fd, foo, 10);
74 fprintf(stderr, " returns %d ", cc);
82 * If we can't determine the interface configuration, just listen with one
83 * socket at the INADDR_ANY address.
88 addrs[0].sin.sin_family = AF_INET;
89 addrs[0].sin.sin_port = 0;
90 addrs[0].sin.sin_addr.s_addr = INADDR_ANY;
91 addrs[0].sin.sin_mask.s_addr = htonl(~0);
92 addrs[0].name = "wildcard";
94 if ((addrs[0].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
95 syslog(LOG_ERR, "socket() failed: %m");
97 perror("socket() failed");
102 if (fcntl(addrs[i].fd, F_SETFL, FNDELAY) < 0) {
103 syslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
105 perror("fcntl(FNDELAY) fails");
109 addrs[0].sin.sin_family = AF_INET;
110 addrs[0].sin.sin_port = port;
111 addrs[0].if_flags = 0;
113 (addrs[0].fd, (struct sockaddr *)&addrs[0].sin,
114 sizeof(addrs[0].sin)) < 0) {
115 syslog(LOG_ERR, "bind() fails: %m");
117 perror("bind fails\n");
126 * Grab interface configuration, and create a socket for each interface
134 struct ifreq ifreq, *ifr;
137 extern char *malloc();
140 * create pseudo-interface with wildcard address
142 addrs[nintf].sin.sin_family = AF_INET;
143 addrs[nintf].sin.sin_port = 0;
144 addrs[nintf].sin.sin_addr.s_addr = INADDR_ANY;
145 addrs[nintf].name = "wild";
146 addrs[nintf].mask.sin_addr.s_addr = htonl(~0);
150 if ((vs = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
151 syslog(LOG_ERR, "vs=socket(AF_INET, SOCK_DGRAM) %m");
153 perror("vs=socket(AF_INET, SOCK_DGRAM)");
157 ifc.ifc_len = sizeof(buf);
159 if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) {
160 syslog(LOG_ERR, "get interface configuration: %m");
162 perror("ioctl(SIOCGIFCONF) fails");
166 n = ifc.ifc_len / sizeof(struct ifreq);
168 for (ifr = ifc.ifc_req; n > 0; n--, ifr++) {
169 if (ifr->ifr_addr.sa_family != AF_INET)
172 if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
173 syslog(LOG_ERR, "get interface flags: %m");
175 perror("SIOCGIFFFLAGS fails");
179 if ((ifreq.ifr_flags & IFF_UP) == 0)
181 addrs[nintf].if_flags = ifreq.ifr_flags;
183 if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) {
184 syslog(LOG_ERR, "get interface addr: %m");
186 perror("SIOCGIFADDR fails");
190 if ((addrs[nintf].name = malloc(strlen(ifreq.ifr_name) + 1))
192 syslog(LOG_ERR, "malloc failed");
195 strcpy(addrs[nintf].name, ifreq.ifr_name);
196 addrs[nintf].sin = *(struct sockaddr_in *)&ifreq.ifr_addr;
198 #ifdef SIOCGIFBRDADDR
199 if (addrs[nintf].if_flags & IFF_BROADCAST) {
200 if (ioctl(vs, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
201 syslog(LOG_ERR, "SIOCGIFBRDADDR fails");
203 perror("SIOCGIFBRDADDR fails");
208 addrs[nintf].bcast = *(struct sockaddr_in *)&ifreq.ifr_broadaddr;
210 addrs[nintf].bcast = *(struct sockaddr_in *)&ifreq.ifr_addr;
213 #endif /* SIOCGIFBRDADDR */
214 #ifdef SIOCGIFNETMASK
215 if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
216 syslog(LOG_ERR, "SIOCGIFNETMASK fails");
218 perror("SIOCGIFNETMASK fails");
222 addrs[nintf].mask = *(struct sockaddr_in *)&ifreq.ifr_addr;
223 #endif /* SIOCGIFNETMASK */
226 * look for an already existing source interface address. If
227 * the machine has multiple point to point interfaces, then
228 * the local address may appear more than once.
230 for (i = 0; i < nintf; i++)
231 if (addrs[i].sin.sin_addr.s_addr ==
232 addrs[nintf].sin.sin_addr.s_addr) {
234 printf("dup interface address %s on %s\n",
235 inet_ntoa(addrs[nintf].sin.sin_addr.s_addr),
245 for (i = 0; i < nintf; i++) {
246 /* create a datagram (UDP) socket */
247 if ((addrs[i].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
248 syslog(LOG_ERR, "socket() failed: %m");
250 perror("socket(AF_INET, SOCK_DGRAM) fails");
255 /* set SO_REUSEADDR since we will be binding the same port
256 * number on each interface */
258 (addrs[i].fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
261 perror("setsockopt SO_REUSEADDR on");
263 syslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails: %m");
267 * set non-blocking I/O on the descriptor
269 if (fcntl(addrs[i].fd, F_SETFL, FNDELAY) < 0) {
270 syslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
272 perror("fcntl(F_SETFL, FNDELAY) fails");
278 * finally, bind the local address address.
280 addrs[i].sin.sin_family = AF_INET;
281 addrs[i].sin.sin_port = port;
283 (addrs[i].fd, (struct sockaddr *)&addrs[i].sin,
284 sizeof(addrs[i].sin)) < 0) {
285 syslog(LOG_ERR, "bind() fails: %m");
287 perror("bind fails");
293 * Turn off the SO_REUSEADDR socket option. It apparently
294 * causes heartburn on systems with multicast IP installed.
295 * On normal systems it only gets looked at when the address
296 * is being bound anyway..
299 (addrs[i].fd, SOL_SOCKET, SO_REUSEADDR, (char *)&off,
301 syslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m");
303 perror("setsockopt SO_REUSEADDR off");
307 /* if this interface can support broadcast, set SO_BROADCAST */
308 if (addrs[i].if_flags & IFF_BROADCAST) {
310 (addrs[i].fd, SOL_SOCKET, SO_BROADCAST, (char *)&on,
312 syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
314 perror("setsockopt(SO_BROADCAST) on");
318 #endif /* SO_BROADCAST */