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