xref: /original-bsd/usr.sbin/amd/amd/wire.c (revision 93152bbe)
1 /*
2  * Copyright (c) 1990 Jan-Simon Pendry
3  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
4  * Copyright (c) 1990 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Jan-Simon Pendry at Imperial College, London.
9  *
10  * %sccs.include.redist.c%
11  *
12  *	@(#)wire.c	5.3 (Berkeley) 05/12/91
13  *
14  * $Id: wire.c,v 5.2.1.5 91/05/07 22:14:21 jsp Alpha $
15  *
16  */
17 
18 /*
19  * This routine returns the subnet (address&netmask) for the primary network
20  * interface.  If the resulting address has an entry in the hosts file, the
21  * corresponding name is retuned, otherwise the address is returned in
22  * standard internet format.
23  *
24  * From: Paul Anderson (23/4/90)
25  */
26 
27 #include "am.h"
28 
29 #include <sys/ioctl.h>
30 
31 #define NO_SUBNET "notknown"
32 
33 #ifdef SIOCGIFFLAGS
34 #include <net/if.h>
35 #include <netdb.h>
36 
37 #if defined(IFF_LOCAL_LOOPBACK) && !defined(IFF_LOOPBACK)
38 #define IFF_LOOPBACK IFF_LOCAL_LOOPBACK
39 #endif
40 
41 #define GFBUFLEN 1024
42 #define clist (ifc.ifc_ifcu.ifcu_req)
43 #define count (ifc.ifc_len/sizeof(struct ifreq))
44 
45 char *getwire P((void));
46 char *getwire()
47 {
48 	struct hostent *hp;
49 	struct netent *np;
50 	struct ifconf ifc;
51 	struct ifreq *ifr;
52 	caddr_t cp, cplim;
53 	unsigned long address, netmask, subnet;
54 	char buf[GFBUFLEN], *s;
55 	int sk = -1;
56 
57 	/*
58 	 * Get suitable socket
59 	 */
60 	if ((sk = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
61 		goto out;
62 
63 	/*
64 	 * Fill in ifconf details
65 	 */
66 	ifc.ifc_len = sizeof buf;
67 	ifc.ifc_buf = buf;
68 
69 	/*
70 	 * Get network interface configurations
71 	 */
72 	if (ioctl(sk, SIOCGIFCONF, (caddr_t) &ifc) < 0)
73 		goto out;
74 
75 	/*
76 	 * Upper bound on array
77 	 */
78 	cplim = buf + ifc.ifc_len;
79 
80 	/*
81 	 * This is some magic to cope with both "traditional" and the
82 	 * new 4.4BSD-style struct sockaddrs.  The new structure has
83 	 * variable length and a size field to support longer addresses.
84 	 * AF_LINK is a new definition for 4.4BSD.
85 	 */
86 #ifdef AF_LINK
87 #define max(a, b) ((a) > (b) ? (a) : (b))
88 #define size(ifr) (max((ifr)->ifr_addr.sa_len, sizeof((ifr)->ifr_addr)) + sizeof(ifr->ifr_name))
89 #else
90 #define size(ifr) sizeof(*ifr)
91 #endif
92 	/*
93 	 * Scan the list looking for a suitable interface
94 	 */
95 	for (cp = buf; cp < cplim; cp += size(ifr)) {
96 		ifr = (struct ifreq *) cp;
97 
98 		if (ifr->ifr_addr.sa_family != AF_INET)
99 			continue;
100 		else
101 			address = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
102 
103 		/*
104 		 * Get interface flags
105 		 */
106 		if (ioctl(sk, SIOCGIFFLAGS, (caddr_t) ifr) < 0)
107 			goto out;
108 
109 		/*
110 		 * If the interface is a loopback, or its not running
111 		 * then ignore it.
112 		 */
113 		if ((ifr->ifr_flags & IFF_LOOPBACK) != 0)
114 			continue;
115 		if ((ifr->ifr_flags & IFF_RUNNING) == 0)
116 			continue;
117 
118 		/*
119 		 * Get the netmask of this interface
120 		 */
121 		if (ioctl(sk, SIOCGIFNETMASK, (caddr_t) ifr) < 0)
122 			goto out;
123 
124 		netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
125 
126 		(void) close(sk);
127 
128 		/*
129 		 * Figure out the subnet's network address
130 		 */
131 		subnet = address & netmask;
132 #ifdef IN_CLASSA
133 		if (IN_CLASSA(subnet))
134 			subnet >>= IN_CLASSA_NSHIFT;
135 		else if (IN_CLASSB(subnet))
136 			subnet >>= IN_CLASSB_NSHIFT;
137 		else if (IN_CLASSC(subnet))
138 			subnet >>= IN_CLASSC_NSHIFT;
139 #endif
140 		/*
141 		 * Now get a usable name.
142 		 * First use the network database,
143 		 * then the host database,
144 		 * and finally just make a dotted quad.
145 		 */
146 		np = getnetbyaddr(subnet, AF_INET);
147 		if (np)
148 			s = np->n_name;
149 		else {
150 			subnet = address & netmask;
151 			hp = gethostbyaddr((char *) &subnet, 4, AF_INET);
152 			if (hp)
153 				s = hp->h_name;
154 			else
155 				s = inet_dquad(buf, subnet);
156 		}
157 
158 		return strdup(s);
159 	}
160 
161 out:
162 	if (sk >= 0)
163 		(void) close(sk);
164 	return strdup(NO_SUBNET);
165 }
166 
167 #else
168 
169 char *getwire P((void));
170 char *getwire()
171 {
172 	return strdup(NO_SUBNET);
173 }
174 #endif /* SIOCGIFFLAGS */
175