Update files for OpenSSL-1.0.1d import.
[dragonfly.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  * $FreeBSD: src/lib/libatm/ioctl_subr.c,v 1.3.2.1 2001/09/28 16:52:10 dillon Exp $
27  * $DragonFly: src/lib/libatm/ioctl_subr.c,v 1.5 2008/09/30 16:57:04 swildner Exp $
28  */
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 int
88 do_info_ioctl(struct atminfreq *req, int 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 = (caddr_t)UM_ALLOC(buf_len);
106         if (buf == NULL) {
107                 errno = ENOMEM;
108                 return(-1);
109         }
110
111         /*
112          * Set the buffer address and length in the request
113          */
114         req->air_buf_addr = buf;
115         req->air_buf_len = buf_len;
116
117         /*
118          * Issue the IOCTL
119          */
120         rc = ioctl(s, AIOCINFO, (caddr_t)req);
121         if (rc) {
122                 UM_FREE(buf);
123                 if (errno == ENOSPC) {
124                         buf_len = buf_len * 2;
125                         goto mem_retry;
126                 }
127                 return(-1);
128         }
129         (void)close(s);
130         /*
131          * Set a pointer to the returned info in the request
132          * and return its length
133          */
134         req->air_buf_addr = buf;
135         return(req->air_buf_len);
136 }
137
138
139 /*
140  * Get VCC information
141  * 
142  * Arguments:
143  *      intf    pointer to interface name (or null string)
144  *      vccp    pointer to a pointer to a struct air_vcc_rsp for the
145  *              address of the returned VCC information
146  *
147  * Returns:
148  *      int     length of the retuned VCC information
149  *
150  */
151 int
152 get_vcc_info(char *intf, struct air_vcc_rsp **vccp)
153 {
154         int     buf_len = sizeof(struct air_vcc_rsp) * 100;
155         struct atminfreq        air;
156
157         /*
158          * Initialize IOCTL request
159          */
160         air.air_opcode = AIOCS_INF_VCC;
161         UM_ZERO(air.air_vcc_intf, sizeof(air.air_vcc_intf));
162         if (intf != NULL && strlen(intf) != 0)
163                 strlcpy(air.air_vcc_intf, intf, IFNAMSIZ);
164
165         buf_len = do_info_ioctl(&air, buf_len);
166
167         /*
168          * Return a pointer to the VCC info and its length
169          */
170         *vccp = (struct air_vcc_rsp *) air.air_buf_addr;
171         return(buf_len);
172 }
173
174
175 /*
176  * Get subnet mask
177  * 
178  * Arguments:
179  *      intf    pointer to an interface name
180  *      mask    pointer to a struct sockaddr_in to receive the mask
181  *
182  * Returns:
183  *      0       good completion
184  *      -1      error
185  *
186  */
187 int
188 get_subnet_mask(char *intf, struct sockaddr_in *mask)
189 {
190         int                     rc, s;
191         struct ifreq            req;
192         struct sockaddr_in      *ip_mask;
193
194         /*
195          * Check parameters
196          */
197         if (!intf || !mask ||
198                         strlen(intf) == 0 ||
199                         strlen(intf) > IFNAMSIZ-1)
200                 return(-1);
201
202         /*
203          * Open a socket for the IOCTL
204          */
205         s = socket(AF_INET, SOCK_DGRAM, 0);
206         if (s < 0)
207                 return(-1);
208
209         /*
210          * Set up and issue the IOCTL
211          */
212         UM_ZERO(&req, sizeof(req));
213         strlcpy(req.ifr_name, intf, sizeof(req.ifr_name));
214         rc = ioctl(s, SIOCGIFNETMASK, (caddr_t)&req);
215         (void)close(s);
216         if (rc)
217                 return(-1);
218
219         /*
220          * Give the answer back to the caller
221          */
222         ip_mask = (struct sockaddr_in *)&req.ifr_addr;
223         *mask = *ip_mask;
224         mask->sin_family = AF_INET;
225
226         return(0);
227 }
228
229
230 /*
231  * Get an interface's MTU
232  * 
233  * Arguments:
234  *      intf    pointer to an interface name
235  *      mtu     pointer to an int to receive the MTU
236  *
237  * Returns:
238  *      >= 0    interface MTU
239  *      -1      error
240  *
241  */
242 int
243 get_mtu(char *intf)
244 {
245         int                     rc, s;
246         struct ifreq            req;
247
248         /*
249          * Check parameters
250          */
251         if (!intf || strlen(intf) == 0 ||
252                         strlen(intf) > IFNAMSIZ-1)
253                 return(-1);
254
255         /*
256          * Open a socket for the IOCTL
257          */
258         s = socket(AF_INET, SOCK_DGRAM, 0);
259         if (s < 0)
260                 return(-1);
261
262         /*
263          * Set up and issue the IOCTL
264          */
265         UM_ZERO(&req, sizeof(req));
266         strlcpy(req.ifr_name, intf, sizeof(req.ifr_name));
267         rc = ioctl(s, SIOCGIFMTU, (caddr_t)&req);
268         (void)close(s);
269
270         /*
271          * Set the appropriate return value
272          */
273         if (rc)
274                 return(-1);
275         else
276         return(req.ifr_mtu);
277 }
278
279
280 /*
281  * Verify netif name
282  * 
283  * This routine issues an IOCTL to check whether the passed string is
284  * a valid network interface name.
285  * 
286  * Arguments:
287  *      req     pointer to an ATM information request IOCTL structure
288  *
289  * Returns:
290  *      -1              error encountered
291  *      FALSE (0)       the string is not a NIF name
292  *      TRUE (> 0)      the string is a valid NIF name
293  *
294  */
295 int
296 verify_nif_name(char *name)
297 {
298         int     rc, s;
299         struct atminfreq        air;
300         struct air_netif_rsp    *nif_info;
301
302         /*
303          * Check whether name is of a valid length
304          */
305         if (strlen(name) > IFNAMSIZ - 1 ||
306                         strlen(name) < 1) {
307                 return(FALSE);
308         }
309
310         /*
311          * Open a socket for the IOCTL
312          */
313         s = socket(AF_ATM, SOCK_DGRAM, 0);
314         if (s < 0) {
315                 return(-1);
316         }
317
318         /*
319          * Get memory for returned information
320          */
321         nif_info = (struct air_netif_rsp *)UM_ALLOC(
322                         sizeof(struct air_netif_rsp));
323         if (nif_info == NULL) {
324                 errno = ENOMEM;
325                 return(-1);
326         }
327
328         /*
329          * Set up the request
330          */
331         air.air_opcode = AIOCS_INF_NIF;
332         air.air_buf_addr = (caddr_t)nif_info;
333         air.air_buf_len = sizeof(struct air_netif_rsp);
334         UM_ZERO(air.air_netif_intf, sizeof(air.air_netif_intf));
335         strlcpy(air.air_netif_intf, name, sizeof(air.air_netif_intf));
336
337         /*
338          * Issue the IOCTL
339          */
340         rc = ioctl(s, AIOCINFO, (caddr_t)&air);
341         UM_FREE(nif_info);
342         (void)close(s);
343
344         /*
345          * Base return value on IOCTL return code
346          */
347         if (rc)
348                 return(FALSE);
349         else
350                 return(TRUE);
351 }
352
353 /*
354  * Get Config information
355  *
356  * Arguments:
357  *      intf    pointer to interface name (or null string)
358  *      cfgp    pointer to a pointer to a struct air_cfg_rsp for the
359  *              address of the returned Config information
360  *
361  * Returns:
362  *      int     length of returned Config information
363  *
364  */
365 int
366 get_cfg_info(char *intf, struct air_cfg_rsp **cfgp)
367 {
368         int     buf_len = sizeof(struct air_cfg_rsp) * 4;
369         struct atminfreq air;
370
371         /*
372          * Initialize IOCTL request
373          */
374         air.air_opcode = AIOCS_INF_CFG;
375         UM_ZERO ( air.air_cfg_intf, sizeof(air.air_cfg_intf));
376         if ( intf != NULL && strlen(intf) != 0 )
377                 strlcpy ( air.air_cfg_intf, intf, IFNAMSIZ );
378
379         buf_len = do_info_ioctl ( &air, buf_len );
380
381         /*
382          * Return a pointer to the Config info and its length
383          */
384         *cfgp = (struct air_cfg_rsp *) air.air_buf_addr;
385         return ( buf_len );
386
387 }
388
389 /*
390  * Get Physical Interface information
391  *
392  * Arguments:
393  *      intf    pointer to interface name (or null string)
394  *      intp    pointer to a pointer to a struct air_cfg_rsp for the
395  *              address of the returned Config information
396  *
397  * Returns:
398  *      int     length of returned Config information
399  *
400  */
401 int
402 get_intf_info(char *intf, struct air_int_rsp **intp)
403 {
404         int     buf_len = sizeof(struct air_int_rsp) * 4;
405         struct atminfreq air;
406
407         /*
408          * Initialize IOCTL request
409          */
410         air.air_opcode = AIOCS_INF_INT;
411         UM_ZERO ( air.air_int_intf, sizeof(air.air_int_intf));
412         if ( intf != NULL && strlen(intf) != 0 )
413                 strlcpy ( air.air_int_intf, intf, IFNAMSIZ );
414
415         buf_len = do_info_ioctl ( &air, buf_len );
416  
417         /*
418          * Return a pointer to the Physical Interface info and its length
419          */
420         *intp = (struct air_int_rsp *) air.air_buf_addr;
421         return ( buf_len );
422
423 }
424
425
426 /*
427  * Get Netif information
428  *
429  * Arguments:
430  *      intf    pointer to interface name (or null string)
431  *      netp    pointer to a pointer to a struct air_netif_rsp for the
432  *              address of the returned Netif information
433  *
434  * Returns:
435  *      int     length of returned Netif information
436  *
437  */
438 int
439 get_netif_info(char *intf, struct air_netif_rsp **netp)
440 {
441         int     buf_len = sizeof(struct air_netif_rsp) * 10;
442         struct atminfreq air;
443
444         /*
445          * Initialize IOCTL request
446          */
447         air.air_opcode = AIOCS_INF_NIF;
448         UM_ZERO ( air.air_int_intf, sizeof(air.air_int_intf) );
449         if ( intf != NULL && strlen(intf) != 0 )
450                 strlcpy ( air.air_int_intf, intf, IFNAMSIZ );
451
452         buf_len = do_info_ioctl ( &air, buf_len );
453
454         /*
455          * Return a pointer to the Netif info and its length
456          */
457         *netp = (struct air_netif_rsp *) air.air_buf_addr;
458         return ( buf_len );
459
460 }