Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / netproto / atm / ipatm / ipatm_usrreq.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/sys/netatm/ipatm/ipatm_usrreq.c,v 1.5.2.1 2003/02/15 09:25:13 phk Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_usrreq.c,v 1.2 2003/06/17 04:28:49 dillon Exp $
28  */
29
30 /*
31  * IP Over ATM Support
32  * -------------------
33  *
34  * Process user requests
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #include <netatm/ipatm/ipatm_var.h>
41 #include <netatm/ipatm/ipatm_serv.h>
42
43 /*
44  * Process IP PF_ATM ioctls
45  * 
46  * Called at splnet.
47  *
48  * Arguments:
49  *      code    PF_ATM sub-operation code
50  *      data    pointer to code specific parameter data area
51  *      arg1    pointer to code specific argument
52  *
53  * Returns:
54  *      0       request procesed
55  *      errno   error processing request - reason indicated
56  *
57  */
58 int
59 ipatm_ioctl(code, data, arg1)
60         int             code;
61         caddr_t         data;
62         caddr_t         arg1;
63 {
64         struct atmaddreq        *aap;
65         struct atmdelreq        *adp;
66         struct atminfreq        *aip;
67         struct air_ip_vcc_rsp   aivr;
68         struct atm_nif  *nip;
69         struct ip_nif   *inp;
70         struct ipvcc    *ivp;
71         struct vccb     *vcp;
72         struct ipatmpvc pv;
73         caddr_t         cp;
74         struct in_addr  ip;
75         int             space, err = 0;
76
77
78         switch (code) {
79
80         case AIOCS_ADD_PVC:
81                 /*
82                  * Add an IP PVC
83                  */
84                 aap = (struct atmaddreq *)data;
85
86                 /*
87                  * Find the IP network interface
88                  */
89                 if ((nip = atm_nifname(aap->aar_pvc_intf)) == NULL) {
90                         err = ENXIO;
91                         break;
92                 }
93
94                 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
95                         if (inp->inf_nif == nip)
96                                 break;
97                 }
98                 if (inp == NULL) {
99                         err = ENXIO;
100                         break;
101                 }
102
103                 /*
104                  * Validate PVC params
105                  */
106                 if (aap->aar_pvc_aal == ATM_AAL5) {
107                         if ((aap->aar_pvc_encaps != ATM_ENC_LLC) &&
108                             (aap->aar_pvc_encaps != ATM_ENC_NULL)) {
109                                 err = EINVAL;
110                                 break;
111                         }
112                 } else if (aap->aar_pvc_aal == ATM_AAL3_4) {
113                         if (aap->aar_pvc_encaps != ATM_ENC_NULL) {
114                                 err = EINVAL;
115                                 break;
116                         }
117                 } else {
118                         err = EINVAL;
119                         break;
120                 }
121
122                 if (aap->aar_pvc_flags & PVC_DYN) {
123                         /*
124                          * For dynamic PVC destination addressing, the
125                          * network interface must have support for this
126                          */
127                         if ((inp->inf_serv == NULL) ||
128                             (inp->inf_serv->is_arp_pvcopen == NULL)) {
129                                 err = EDESTADDRREQ;
130                                 break;
131                         }
132                 } else {
133                         u_long  dst = ((struct sockaddr_in *)&aap->aar_pvc_dst)
134                                                 ->sin_addr.s_addr;
135
136                         if (dst == INADDR_ANY) {
137                                 err = EINVAL;
138                                 break;
139                         }
140                 }
141
142                 /*
143                  * Build connection request
144                  */
145                 pv.ipp_ipnif = inp;
146                 pv.ipp_vpi = aap->aar_pvc_vpi;
147                 pv.ipp_vci = aap->aar_pvc_vci;
148                 pv.ipp_encaps = aap->aar_pvc_encaps;
149                 pv.ipp_aal = aap->aar_pvc_aal;
150                 if (aap->aar_pvc_flags & PVC_DYN) {
151                         pv.ipp_dst.sin_addr.s_addr = INADDR_ANY;
152                 } else
153                         pv.ipp_dst = *(struct sockaddr_in *)&aap->aar_pvc_dst;
154
155                 /*
156                  * Open a new VCC
157                  */
158                 err = ipatm_openpvc(&pv, &ivp);
159                 break;
160
161         case AIOCS_ADD_ARP:
162                 /*
163                  * Add an ARP mapping
164                  */
165                 aap = (struct atmaddreq *)data;
166
167                 /*
168                  * Validate IP address
169                  */
170                 if (aap->aar_arp_dst.sa_family != AF_INET) {
171                         err = EAFNOSUPPORT;
172                         break;
173                 }
174                 ip = SATOSIN(&aap->aar_arp_dst)->sin_addr;
175
176                 if (aap->aar_arp_intf[0] == '\0') {
177                         /*
178                          * Find the IP network interface associated with
179                          * the supplied IP address
180                          */
181                         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
182                                 if (ipatm_chknif(ip, inp) == 0)
183                                         break;
184                         }
185                         if (inp == NULL) {
186                                 err = EADDRNOTAVAIL;
187                                 break;
188                         }
189                 } else {
190                         /*
191                          * Find the specified IP network interface
192                          */
193                         if ((nip = atm_nifname(aap->aar_arp_intf)) == NULL) {
194                                 err = ENXIO;
195                                 break;
196                         }
197                         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
198                                 if (inp->inf_nif == nip)
199                                         break;
200                         }
201                         if (inp == NULL) {
202                                 err = ENXIO;
203                                 break;
204                         }
205                 }
206
207                 if ((ip.s_addr == INADDR_ANY) ||
208 #if (defined(BSD) && (BSD >= 199306))   
209                     in_broadcast(ip, &inp->inf_nif->nif_if) ||
210 #else
211                     in_broadcast(ip) ||
212 #endif
213                     IN_MULTICAST(ntohl(ip.s_addr))) {
214                         err = EADDRNOTAVAIL;
215                         break;
216                 }
217
218                 /*
219                  * Notify the responsible ARP service
220                  *
221                  * XXX: if there is one.  No idea how this happens, but at
222                  * least don't panic on a NULL pointer if it does.
223                  */
224                 if (inp->inf_serv == NULL) {
225                         err = ENXIO;
226                         break;
227                 }
228                 err = (*inp->inf_serv->is_ioctl)(code, data, inp->inf_isintf);
229                 break;
230
231         case AIOCS_DEL_ARP:
232                 /*
233                  * Delete an ARP mapping
234                  */
235                 adp = (struct atmdelreq *)data;
236
237                 /*
238                  * Validate IP address
239                  */
240                 if (adp->adr_arp_dst.sa_family != AF_INET) {
241                         err = EAFNOSUPPORT;
242                         break;
243                 }
244                 ip = SATOSIN(&adp->adr_arp_dst)->sin_addr;
245
246                 if (adp->adr_arp_intf[0] == '\0') {
247                         /*
248                          * Find the IP network interface associated with
249                          * the supplied IP address
250                          */
251                         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
252                                 if (ipatm_chknif(ip, inp) == 0)
253                                         break;
254                         }
255                         if (inp == NULL) {
256                                 err = EADDRNOTAVAIL;
257                                 break;
258                         }
259                 } else {
260                         /*
261                          * Find the specified IP network interface
262                          */
263                         if ((nip = atm_nifname(adp->adr_arp_intf)) == NULL) {
264                                 err = ENXIO;
265                                 break;
266                         }
267                         for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
268                                 if (inp->inf_nif == nip)
269                                         break;
270                         }
271                         if (inp == NULL) {
272                                 err = ENXIO;
273                                 break;
274                         }
275                 }
276
277                 if ((ip.s_addr == INADDR_ANY) ||
278 #if (defined(BSD) && (BSD >= 199306))   
279                     in_broadcast(ip, &inp->inf_nif->nif_if) ||
280 #else
281                     in_broadcast(ip) ||
282 #endif
283                     IN_MULTICAST(ntohl(ip.s_addr))) {
284                         err = EADDRNOTAVAIL;
285                         break;
286                 }
287
288                 /*
289                  * Notify the responsible ARP service
290                  */
291                 err = (*inp->inf_serv->is_ioctl)(code, data, inp->inf_isintf);
292                 break;
293
294         case AIOCS_INF_IPM:
295                 /*
296                  * Get IP VCC information
297                  */
298                 aip = (struct atminfreq *)data;
299
300                 if (aip->air_ip_addr.sa_family != AF_INET)
301                         break;
302                 ip = SATOSIN(&aip->air_ip_addr)->sin_addr;
303
304                 cp = aip->air_buf_addr;
305                 space = aip->air_buf_len;
306
307                 /*
308                  * Loop through all our interfaces
309                  */
310                 for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
311                         /*
312                          * Check out each VCC
313                          */
314                         for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
315                                     ivp = Q_NEXT(ivp, struct ipvcc, iv_elem)) {
316
317                                 if ((ip.s_addr != INADDR_ANY) &&
318                                     (ip.s_addr != ivp->iv_dst.s_addr))
319                                         continue;
320
321                                 /*
322                                  * Make sure there's room in user buffer
323                                  */
324                                 if (space < sizeof(aivr)) {
325                                         err = ENOSPC;
326                                         break;
327                                 }
328
329                                 /*
330                                  * Fill in info to be returned
331                                  */
332                                 KM_ZERO((caddr_t)&aivr, sizeof(aivr));
333                                 SATOSIN(&aivr.aip_dst_addr)->sin_family = 
334                                         AF_INET;
335                                 SATOSIN(&aivr.aip_dst_addr)->sin_addr.s_addr = 
336                                         ivp->iv_dst.s_addr;
337                                 (void) snprintf(aivr.aip_intf,
338                                     sizeof(aivr.aip_intf), "%s%d",
339                                         inp->inf_nif->nif_if.if_name,
340                                         inp->inf_nif->nif_if.if_unit);
341                                 if ((ivp->iv_conn) &&
342                                     (ivp->iv_conn->co_connvc) &&
343                                     (vcp = ivp->iv_conn->co_connvc->cvc_vcc)) {
344                                         aivr.aip_vpi = vcp->vc_vpi;
345                                         aivr.aip_vci = vcp->vc_vci;
346                                         aivr.aip_sig_proto = vcp->vc_proto;
347                                 } 
348                                 aivr.aip_flags = ivp->iv_flags;
349                                 aivr.aip_state = ivp->iv_state;
350
351                                 /*
352                                  * Copy data to user buffer and 
353                                  * update buffer controls
354                                  */
355                                 err = copyout((caddr_t)&aivr, cp, sizeof(aivr));
356                                 if (err)
357                                         break;
358                                 cp += sizeof(aivr);
359                                 space -= sizeof(aivr);
360                         }
361                         if (err)
362                                 break;
363                 }
364
365                 /*
366                  * Update buffer pointer/count
367                  */
368                 aip->air_buf_addr = cp;
369                 aip->air_buf_len = space;
370                 break;
371
372         default:
373                 err = EOPNOTSUPP;
374         }
375
376         return (err);
377 }
378
379
380 /*
381  * Get Connection's Application/Owner Name
382  * 
383  * Arguments:
384  *      tok     ipatm connection token (pointer to ipvcc)
385  *
386  * Returns:
387  *      addr    pointer to string containing our name
388  *
389  */
390 caddr_t
391 ipatm_getname(tok)
392         void            *tok;
393 {
394         return ("IP");
395 }
396