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