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 <afs/param.h>
11 #include <afsconfig.h>
15 #include <sys/types.h>
16 #include <sys/param.h>
20 #include <sys/ioctl.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
35 struct intf addrs[MAX_INTF];
41 #include "AFS_component_version_number.c"
47 syslog(LOG_ERR, "ifconfig test");
48 create_sockets(htons(43242));
49 for (i = 0; i < nintf; i++) {
50 printf("%d: %s fd %d addr %s mask %x ",
51 i, addrs[i].name, addrs[i].fd,
52 inet_ntoa(addrs[i].sin.sin_addr.s_addr),
53 ntohl(addrs[i].mask.sin_addr.s_addr));
55 if (getsockopt(addrs[0].fd, SOL_SOCKET, SO_BROADCAST,
60 printf("BCAST opt %d", val);
62 if (getsockopt(addrs[0].fd, SOL_SOCKET, SO_RCVBUF,
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");
103 if (fcntl(addrs[i].fd, F_SETFL, FNDELAY) < 0) {
104 syslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
106 perror("fcntl(FNDELAY) fails");
111 addrs[0].sin.sin_family = AF_INET;
112 addrs[0].sin.sin_port = port;
113 addrs[0].if_flags = 0;
114 if (bind(addrs[0].fd, (struct sockaddr *)&addrs[0].sin,
115 sizeof(addrs[0].sin)) < 0) {
116 syslog(LOG_ERR, "bind() fails: %m");
118 perror("bind fails\n");
127 * Grab interface configuration, and create a socket for each interface
135 struct ifreq ifreq, *ifr;
138 extern char *malloc();
141 * create pseudo-interface with wildcard address
143 addrs[nintf].sin.sin_family = AF_INET;
144 addrs[nintf].sin.sin_port = 0;
145 addrs[nintf].sin.sin_addr.s_addr = INADDR_ANY;
146 addrs[nintf].name = "wild";
147 addrs[nintf].mask.sin_addr.s_addr = htonl(~0);
151 if ((vs = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
152 syslog(LOG_ERR, "vs=socket(AF_INET, SOCK_DGRAM) %m");
154 perror("vs=socket(AF_INET, SOCK_DGRAM)");
158 ifc.ifc_len = sizeof(buf);
160 if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) {
161 syslog(LOG_ERR, "get interface configuration: %m");
163 perror("ioctl(SIOCGIFCONF) fails");
167 n = ifc.ifc_len/sizeof(struct ifreq);
169 for (ifr = ifc.ifc_req; n > 0; n--, ifr++) {
170 if (ifr->ifr_addr.sa_family != AF_INET)
173 if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
174 syslog(LOG_ERR, "get interface flags: %m");
176 perror("SIOCGIFFFLAGS fails");
180 if ((ifreq.ifr_flags & IFF_UP) == 0)
182 addrs[nintf].if_flags = ifreq.ifr_flags;
184 if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) {
185 syslog(LOG_ERR, "get interface addr: %m");
187 perror("SIOCGIFADDR fails");
191 if ((addrs[nintf].name = malloc(strlen(ifreq.ifr_name)+1))
193 syslog(LOG_ERR, "malloc failed");
196 strcpy(addrs[nintf].name, ifreq.ifr_name);
197 addrs[nintf].sin = *(struct sockaddr_in *)&ifreq.ifr_addr;
199 #ifdef SIOCGIFBRDADDR
200 if (addrs[nintf].if_flags & IFF_BROADCAST) {
201 if (ioctl(vs, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
202 syslog(LOG_ERR, "SIOCGIFBRDADDR fails");
204 perror("SIOCGIFBRDADDR fails");
210 *(struct sockaddr_in *)&ifreq.ifr_broadaddr;
213 *(struct sockaddr_in *)&ifreq.ifr_addr;
216 #endif /* SIOCGIFBRDADDR */
217 #ifdef SIOCGIFNETMASK
218 if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
219 syslog(LOG_ERR, "SIOCGIFNETMASK fails");
221 perror("SIOCGIFNETMASK fails");
225 addrs[nintf].mask = *(struct sockaddr_in *)&ifreq.ifr_addr;
226 #endif /* SIOCGIFNETMASK */
229 * look for an already existing source interface address. If
230 * the machine has multiple point to point interfaces, then
231 * the local address may appear more than once.
233 for (i=0; i < nintf; i++)
234 if (addrs[i].sin.sin_addr.s_addr ==
235 addrs[nintf].sin.sin_addr.s_addr) {
237 printf("dup interface address %s on %s\n",
238 inet_ntoa(addrs[nintf].sin.sin_addr.s_addr),
248 for (i = 0; i < nintf; i++) {
249 /* create a datagram (UDP) socket */
250 if ((addrs[i].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
251 syslog(LOG_ERR, "socket() failed: %m");
253 perror("socket(AF_INET, SOCK_DGRAM) fails");
259 /* set SO_REUSEADDR since we will be binding the same port
260 number on each interface */
261 if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_REUSEADDR,
262 (char *)&on, sizeof(on))) {
264 perror("setsockopt SO_REUSEADDR on");
266 syslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails: %m");
270 * set non-blocking I/O on the descriptor
272 if (fcntl(addrs[i].fd, F_SETFL, FNDELAY) < 0) {
273 syslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
275 perror("fcntl(F_SETFL, FNDELAY) fails");
282 * finally, bind the local address address.
284 addrs[i].sin.sin_family = AF_INET;
285 addrs[i].sin.sin_port = port;
286 if (bind(addrs[i].fd, (struct sockaddr *)&addrs[i].sin,
287 sizeof(addrs[i].sin)) < 0) {
288 syslog(LOG_ERR, "bind() fails: %m");
290 perror("bind fails");
296 * Turn off the SO_REUSEADDR socket option. It apparently
297 * causes heartburn on systems with multicast IP installed.
298 * On normal systems it only gets looked at when the address
299 * is being bound anyway..
301 if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_REUSEADDR,
302 (char *)&off, sizeof(off))) {
303 syslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m");
305 perror("setsockopt SO_REUSEADDR off");
310 /* if this interface can support broadcast, set SO_BROADCAST */
311 if (addrs[i].if_flags & IFF_BROADCAST) {
312 if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_BROADCAST,
313 (char *)&on, sizeof(on))) {
314 syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
316 perror("setsockopt(SO_BROADCAST) on");
320 #endif /* SO_BROADCAST */