~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201207201942

« back to all changes in this revision

Viewing changes to lib/netUtil/netUtilLinux.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-03-20 10:19:00 UTC
  • mfrom: (1.1.4 upstream) (2.4.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090320101900-1o604camiubq2de8
Tags: 2009.03.18-154848-2
Correcting patch system depends (Closes: #520493).

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
#include "str.h"
71
71
 
72
72
#define MAX_IFACES      4
73
 
#define LOOPBACK        "lo"
 
73
#define LOOPBACK        "lo"    // XXX: We would have a problem with something like "loa0".
74
74
#ifndef INET_ADDRSTRLEN
75
75
#define INET_ADDRSTRLEN 16
76
76
#endif
77
77
 
78
78
 
79
79
/*
 
80
 *-----------------------------------------------------------------------------
 
81
 *
 
82
 * ValidateConvertAddress --
 
83
 *
 
84
 *      Helper routine validates an address as a return value for
 
85
 *      NetUtil_GetPrimaryIP.
 
86
 *
 
87
 * Results:
 
88
 *      Returns TRUE with sufficient result stored in outputBuffer on success.
 
89
 *      Returns FALSE with "" stored in outputBuffer on failure.
 
90
 *
 
91
 * Side effects:
 
92
 *      None.
 
93
 *
 
94
 *-----------------------------------------------------------------------------
 
95
 */
 
96
 
 
97
static Bool
 
98
ValidateConvertAddress(const char *ifaceName,           // IN: interface name
 
99
                       const struct sockaddr_in *addr,  // IN: network address to
 
100
                                                        //     evaluate
 
101
                       char ipstr[INET_ADDRSTRLEN])     // OUT: converted address
 
102
                                                        //      stored here
 
103
{
 
104
   /*
 
105
    * 1.  Ensure this isn't a loopback device.
 
106
    * 2.  Ensure this is an (IPv4) internet address.
 
107
    */
 
108
   if (ifaceName[0] == '\0' ||
 
109
       strncmp(ifaceName, LOOPBACK, sizeof LOOPBACK - 1) == 0 ||
 
110
       addr->sin_family != AF_INET) {
 
111
      goto invalid;
 
112
   }
 
113
 
 
114
   /*
 
115
    * Branches separated because it just looked really silly to lump the
 
116
    * initial argument checking and actual conversion logic together.
 
117
    */
 
118
 
 
119
   /*
 
120
    * 3.  Attempt network to presentation conversion.
 
121
    * 4.  Ensure the IP isn't all zeros.
 
122
    */
 
123
   if (inet_ntop(AF_INET, (void *)&addr->sin_addr, ipstr, INET_ADDRSTRLEN) != NULL &&
 
124
       strcmp(ipstr, "0.0.0.0") != 0) {
 
125
      return TRUE;
 
126
   }
 
127
 
 
128
invalid:
 
129
   ipstr[0] = '\0';
 
130
   return FALSE;
 
131
}
 
132
 
 
133
 
 
134
/*
80
135
 *----------------------------------------------------------------------
81
136
 *
82
137
 * NetUtil_GetPrimaryIP --
84
139
 *      Get the primary IP for this machine.
85
140
 *
86
141
 * Results:
87
 
 *      
88
 
 *      The IP or NULL if an error occurred.
 
142
 *      If applicable address found, returns string of said IP address.
 
143
 *      If applicable address not found, returns an empty string.
 
144
 *      If an error occurred, returns NULL.
89
145
 *
90
146
 * Side effects:
91
 
 *
92
 
 *      None.
 
147
 *      Caller is responsible for free()ing returned string.
93
148
 *
94
149
 *----------------------------------------------------------------------
95
150
 */
101
156
   int sd, i;
102
157
   struct ifconf iflist;
103
158
   struct ifreq ifaces[MAX_IFACES];
104
 
   char *ipstr;
 
159
   char ipstr[INET_ADDRSTRLEN] = "";
105
160
 
106
161
   /* Get a socket descriptor to give to ioctl(). */
107
162
   sd = socket(PF_INET, SOCK_STREAM, 0);
108
163
   if (sd < 0) {
109
 
      goto error;
 
164
      return NULL;
110
165
   }
111
166
 
112
167
   memset(&iflist, 0, sizeof iflist);
118
173
 
119
174
   if (ioctl(sd, SIOCGIFCONF, &iflist) < 0) {
120
175
      close(sd);
121
 
      goto error;
 
176
      return NULL;
122
177
   }
123
178
 
124
179
   close(sd);
125
180
 
126
181
   /* Loop through the list of interfaces provided by ioctl(). */
127
182
   for (i = 0; i < (sizeof ifaces/sizeof *ifaces); i++) {
128
 
      /*
129
 
       * Find the first interface whose name is not blank and isn't a
130
 
       * loopback device.  This should be the primary interface.
131
 
       */
132
 
      if ((*ifaces[i].ifr_name != '\0') &&
133
 
          (strncmp(ifaces[i].ifr_name, LOOPBACK, strlen(LOOPBACK)) != 0)) {
134
 
         struct sockaddr_in *addr;
135
 
 
136
 
         /*
137
 
          * Allocate memory to return to caller; they must free this if we
138
 
          * don't return error.
139
 
          */
140
 
         ipstr = calloc(1, INET_ADDRSTRLEN);
141
 
         if (!ipstr) {
142
 
            goto error;
143
 
         }
144
 
 
145
 
         addr = (struct sockaddr_in *)(&ifaces[i].ifr_addr);
146
 
 
147
 
         /* Convert this address to dotted decimal */
148
 
         if (inet_ntop(AF_INET, (void *)&addr->sin_addr,
149
 
                       ipstr, INET_ADDRSTRLEN) == NULL) {
150
 
            goto error_free;
151
 
         }
152
 
 
153
 
         /* We'd rather return NULL than an IP of zeros. */
154
 
         if (strcmp(ipstr, "0.0.0.0") == 0) {
155
 
            goto error_free;
156
 
         }
157
 
 
158
 
         return ipstr;
 
183
      if (ValidateConvertAddress(ifaces[i].ifr_name,
 
184
                                 (struct sockaddr_in *)&ifaces[i].ifr_addr,
 
185
                                 ipstr)) {
 
186
         break;
159
187
      }
160
188
   }
161
189
 
162
 
   /* Making it through loop means no non-loopback devices were found. */
163
 
   return NULL;
164
 
 
165
 
error_free:
166
 
   free(ipstr);
167
 
error:
168
 
   return NULL;
 
190
   /* Success.  Here, caller, you can throw this away. */
 
191
   return strdup(ipstr);
169
192
}
170
193
 
171
194
#else /* } FreeBSD || APPLE { */
175
198
{
176
199
   struct ifaddrs *ifaces;
177
200
   struct ifaddrs *curr;
178
 
   char ipstr[INET_ADDRSTRLEN];
 
201
   char ipstr[INET_ADDRSTRLEN] = "";
179
202
 
180
203
   /*
181
204
    * getifaddrs(3) creates a NULL terminated linked list of interfaces for us
185
208
      return NULL;
186
209
   }
187
210
 
188
 
   if (!ifaces) {
189
 
      return NULL;
190
 
   }
191
 
 
192
211
   /*
193
212
    * We traverse the list until there are no more interfaces or we have found
194
213
    * the primary interface.  This function defines the primary interface to be
195
214
    * the first non-loopback, internet interface in the interface list.
196
215
    */
197
216
   for(curr = ifaces; curr != NULL; curr = curr->ifa_next) {
198
 
      struct sockaddr_in *addr;
199
 
 
200
 
      /* Ensure this isn't a loopback device. */
201
 
      if (strncmp(curr->ifa_name, LOOPBACK, strlen(LOOPBACK)) == 0) {
202
 
         continue;
203
 
      }
204
 
 
205
 
      addr = (struct sockaddr_in *)(curr->ifa_addr);
206
 
 
207
 
      /* Ensure this is an (IPv4) internet interface. */
208
 
      if (addr->sin_family == AF_INET) {
209
 
         memset(ipstr, 0, sizeof ipstr);
210
 
 
211
 
         /* Attempt network to presentation conversion. */
212
 
         if (inet_ntop(AF_INET, (void *)&addr->sin_addr, ipstr, sizeof ipstr) == NULL) {
213
 
            continue;
214
 
         }
215
 
 
216
 
         /* If the IP is all zeros we'll try for another interface. */
217
 
         if (strcmp(ipstr, "0.0.0.0") == 0) {
218
 
            /* Empty the string so we never return "0.0.0.0". */
219
 
            ipstr[0] = '\0';
220
 
            continue;
221
 
         }
222
 
 
223
 
         /*
224
 
          * We have found the primary interface and its dotted-decimal IP is
225
 
          * in ipstr.
226
 
          */
 
217
      if (ValidateConvertAddress(curr->ifa_name,
 
218
                                 (struct sockaddr_in *)curr->ifa_addr,
 
219
                                 ipstr)) {
227
220
         break;
228
221
      }
229
222
   }
231
224
   /* Tell FreeBSD to free our linked list. */
232
225
   freeifaddrs(ifaces);
233
226
 
234
 
   /*
235
 
    * If ipstr is blank, just return NULL.  Otherwise, we create a copy of the
236
 
    * string and return the pointer; the caller must free this memory.
237
 
    */
238
 
   return (ipstr[0] == '\0') ? NULL : strdup(ipstr);
 
227
   /* Success.  Here, caller, you can throw this away. */
 
228
   return strdup(ipstr);
239
229
}
240
230
#endif /* } */
241
231