]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libatm/ioctl_subr.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / lib / libatm / ioctl_subr.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 /*
31  * User Space Library Functions
32  * ----------------------------
33  *
34  * IOCTL subroutines
35  *
36  */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <sys/sockio.h>
42 #include <net/if.h>
43 #include <netinet/in.h>
44 #include <netatm/port.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_if.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_sys.h>
49 #include <netatm/atm_ioctl.h>
50
51 #include <errno.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55
56 #include "libatm.h"
57
58 #ifndef TRUE
59 #define TRUE    1
60 #endif
61
62 #ifndef FALSE
63 #define FALSE   0
64 #endif
65
66 extern char     *prog;
67
68
69 /*
70  * Issue an informational IOCTL
71  * 
72  * The user fills out the opcode and any subtype information.  This
73  * routine will allocate a buffer and issue the IOCTL.  If the request
74  * fails because the buffer wasn't big enough, this routine will double
75  * the buffer size and retry the request repeatedly.  The buffer must
76  * be freed by the caller.
77  * 
78  * Arguments:
79  *      req     pointer to an ATM information request IOCTL structure
80  *      buf_len length of buffer to be allocated
81  *
82  * Returns:
83  *      -1      error encountered (reason in errno)
84  *      int     length of the returned VCC information
85  *
86  */
87 ssize_t
88 do_info_ioctl(struct atminfreq *req, size_t buf_len)
89 {
90         int     rc, s;
91         caddr_t buf;
92
93         /*
94          * Open a socket for the IOCTL
95          */
96         s = socket(AF_ATM, SOCK_DGRAM, 0);
97         if (s < 0) {
98                 return(-1);
99         }
100
101         /*
102          * Get memory for returned information
103          */
104 mem_retry:
105         buf = malloc(buf_len);
106         if (buf == NULL) {
107                 errno = ENOMEM;
108                 return(-1);
109         }
110         bzero(buf, buf_len);
111
112         /*
113          * Set the buffer address and length in the request
114          */
115         req->air_buf_addr = buf;
116         req->air_buf_len = buf_len;
117
118         /*
119          * Issue the IOCTL
120          */
121         rc = ioctl(s, AIOCINFO, (caddr_t)req);
122         if (rc) {
123                 free(buf);
124                 if (errno == ENOSPC) {
125                         buf_len = buf_len * 2;
126                         goto mem_retry;
127                 }
128                 return(-1);
129         }
130         (void)close(s);
131         /*
132          * Set a pointer to the returned info in the request
133          * and return its length
134          */
135         req->air_buf_addr = buf;
136         return(req->air_buf_len);
137 }
138
139
140 /*
141  * Get VCC information
142  * 
143  * Arguments:
144  *      intf    pointer to interface name (or null string)
145  *      vccp    pointer to a pointer to a struct air_vcc_rsp for the
146  *              address of the returned VCC information
147  *
148  * Returns:
149  *      int     length of the retuned VCC information
150  *
151  */
152 ssize_t
153 get_vcc_info(const char *intf, struct air_vcc_rsp **vccp)
154 {
155         size_t buf_len = sizeof(struct air_vcc_rsp) * 100;
156         struct atminfreq air;
157
158         /*
159          * Initialize IOCTL request
160          */
161         air.air_opcode = AIOCS_INF_VCC;
162         bzero(air.air_vcc_intf, sizeof(air.air_vcc_intf));
163         if (intf != NULL && strlen(intf) != 0)
164                 strncpy(air.air_vcc_intf, intf, IFNAMSIZ - 1);
165
166         buf_len = do_info_ioctl(&air, buf_len);
167
168         /*
169          * Return a pointer to the VCC info and its length
170          */
171         *vccp = (struct air_vcc_rsp *)(void *)air.air_buf_addr;
172         return(buf_len);
173 }
174
175
176 /*
177  * Get subnet mask
178  * 
179  * Arguments:
180  *      intf    pointer to an interface name
181  *      mask    pointer to a struct sockaddr_in to receive the mask
182  *
183  * Returns:
184  *      0       good completion
185  *      -1      error
186  *
187  */
188 int
189 get_subnet_mask(const char *intf, struct sockaddr_in *mask)
190 {
191         int                     rc, s;
192         struct ifreq            req;
193         struct sockaddr_in      *ip_mask;
194
195         /*
196          * Check parameters
197          */
198         if (!intf || !mask ||
199                         strlen(intf) == 0 ||
200                         strlen(intf) > IFNAMSIZ-1)
201                 return(-1);
202
203         /*
204          * Open a socket for the IOCTL
205          */
206         s = socket(AF_INET, SOCK_DGRAM, 0);
207         if (s < 0)
208                 return(-1);
209
210         /*
211          * Set up and issue the IOCTL
212          */
213         bzero(&req, sizeof(req));
214         strcpy(req.ifr_name, intf);
215         rc = ioctl(s, SIOCGIFNETMASK, (caddr_t)&req);
216         (void)close(s);
217         if (rc)
218                 return(-1);
219
220         /*
221          * Give the answer back to the caller
222          */
223         ip_mask = (struct sockaddr_in *)(void *)&req.ifr_addr;
224         *mask = *ip_mask;
225         mask->sin_family = AF_INET;
226
227         return(0);
228 }
229
230
231 /*
232  * Get an interface's MTU
233  * 
234  * Arguments:
235  *      intf    pointer to an interface name
236  *      mtu     pointer to an int to receive the MTU
237  *
238  * Returns:
239  *      >= 0    interface MTU
240  *      -1      error
241  *
242  */
243 int
244 get_mtu(const char *intf)
245 {
246         int                     rc, s;
247         struct ifreq            req;
248
249         /*
250          * Check parameters
251          */
252         if (!intf || strlen(intf) == 0 ||
253                         strlen(intf) > IFNAMSIZ-1)
254                 return(-1);
255
256         /*
257          * Open a socket for the IOCTL
258          */
259         s = socket(AF_INET, SOCK_DGRAM, 0);
260         if (s < 0)
261                 return(-1);
262
263         /*
264          * Set up and issue the IOCTL
265          */
266         bzero(&req, sizeof(req));
267         strcpy(req.ifr_name, intf);
268         rc = ioctl(s, SIOCGIFMTU, (caddr_t)&req);
269         (void)close(s);
270
271         /*
272          * Set the appropriate return value
273          */
274         if (rc)
275                 return(-1);
276         else
277         return(req.ifr_mtu);
278 }
279
280
281 /*
282  * Verify netif name
283  * 
284  * This routine issues an IOCTL to check whether the passed string is
285  * a valid network interface name.
286  * 
287  * Arguments:
288  *      req     pointer to an ATM information request IOCTL structure
289  *
290  * Returns:
291  *      -1              error encountered
292  *      FALSE (0)       the string is not a NIF name
293  *      TRUE (> 0)      the string is a valid NIF name
294  *
295  */
296 int
297 verify_nif_name(const char *name)
298 {
299         int     rc, s;
300         struct atminfreq        air;
301         struct air_netif_rsp    *nif_info;
302
303         /*
304          * Check whether name is of a valid length
305          */
306         if (strlen(name) > IFNAMSIZ - 1 ||
307                         strlen(name) < 1) {
308                 return(FALSE);
309         }
310
311         /*
312          * Open a socket for the IOCTL
313          */
314         s = socket(AF_ATM, SOCK_DGRAM, 0);
315         if (s < 0) {
316                 return(-1);
317         }
318
319         /*
320          * Get memory for returned information
321          */
322         nif_info = malloc(sizeof(struct air_netif_rsp));
323         if (nif_info == NULL) {
324                 errno = ENOMEM;
325                 return(-1);
326         }
327         bzero(nif_info, sizeof(struct air_netif_rsp));
328
329         /*
330          * Set up the request
331          */
332         air.air_opcode = AIOCS_INF_NIF;
333         air.air_buf_addr = (caddr_t)nif_info;
334         air.air_buf_len = sizeof(struct air_netif_rsp);
335         bzero(air.air_netif_intf, sizeof(air.air_netif_intf));
336         strcpy(air.air_netif_intf, name);
337
338         /*
339          * Issue the IOCTL
340          */
341         rc = ioctl(s, AIOCINFO, (caddr_t)&air);
342         free(nif_info);
343         (void)close(s);
344
345         /*
346          * Base return value on IOCTL return code
347          */
348         if (rc)
349                 return(FALSE);
350         else
351                 return(TRUE);
352 }
353
354 /*
355  * Get Config information
356  *
357  * Arguments:
358  *      intf    pointer to interface name (or null string)
359  *      cfgp    pointer to a pointer to a struct air_cfg_rsp for the
360  *              address of the returned Config information
361  *
362  * Returns:
363  *      int     length of returned Config information
364  *
365  */
366 ssize_t
367 get_cfg_info(const char *intf, struct air_cfg_rsp **cfgp)
368 {
369         size_t buf_len = sizeof(struct air_cfg_rsp) * 4;
370         struct atminfreq air;
371
372         /*
373          * Initialize IOCTL request
374          */
375         air.air_opcode = AIOCS_INF_CFG;
376         bzero ( air.air_cfg_intf, sizeof(air.air_cfg_intf));
377         if ( intf != NULL && strlen(intf) != 0 )
378                 strncpy(air.air_cfg_intf, intf, IFNAMSIZ - 1);
379
380         buf_len = do_info_ioctl ( &air, buf_len );
381
382         /*
383          * Return a pointer to the Config info and its length
384          */
385         *cfgp = (struct air_cfg_rsp *)(void *)air.air_buf_addr;
386         return ( buf_len );
387
388 }
389
390 /*
391  * Get Physical Interface information
392  *
393  * Arguments:
394  *      intf    pointer to interface name (or null string)
395  *      intp    pointer to a pointer to a struct air_cfg_rsp for the
396  *              address of the returned Config information
397  *
398  * Returns:
399  *      int     length of returned Config information
400  *
401  */
402 ssize_t
403 get_intf_info(const char *intf, struct air_int_rsp **intp)
404 {
405         size_t buf_len = sizeof(struct air_int_rsp) * 4;
406         struct atminfreq air;
407
408         /*
409          * Initialize IOCTL request
410          */
411         air.air_opcode = AIOCS_INF_INT;
412         bzero ( air.air_int_intf, sizeof(air.air_int_intf));
413         if ( intf != NULL && strlen(intf) != 0 )
414                 strncpy(air.air_int_intf, intf, IFNAMSIZ - 1);
415
416         buf_len = do_info_ioctl ( &air, buf_len );
417  
418         /*
419          * Return a pointer to the Physical Interface info and its length
420          */
421         *intp = (struct air_int_rsp *)(void *)air.air_buf_addr;
422         return ( buf_len );
423
424 }
425
426
427 /*
428  * Get Netif information
429  *
430  * Arguments:
431  *      intf    pointer to interface name (or null string)
432  *      netp    pointer to a pointer to a struct air_netif_rsp for the
433  *              address of the returned Netif information
434  *
435  * Returns:
436  *      int     length of returned Netif information
437  *
438  */
439 ssize_t
440 get_netif_info(const char *intf, struct air_netif_rsp **netp)
441 {
442         size_t buf_len = sizeof(struct air_netif_rsp) * 10;
443         struct atminfreq air;
444
445         /*
446          * Initialize IOCTL request
447          */
448         air.air_opcode = AIOCS_INF_NIF;
449         bzero ( air.air_int_intf, sizeof(air.air_int_intf) );
450         if ( intf != NULL && strlen(intf) != 0 )
451                 strncpy(air.air_int_intf, intf, IFNAMSIZ - 1);
452
453         buf_len = do_info_ioctl ( &air, buf_len );
454
455         /*
456          * Return a pointer to the Netif info and its length
457          */
458         *netp = (struct air_netif_rsp *) air.air_buf_addr;
459         return ( buf_len );
460
461 }