dd1013c9b4b5962fd18a836cecb496f363d2f405
[dragonfly.git] / sys / netproto / atm / ipatm / ipatm_load.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_load.c,v 1.6 2000/01/17 20:49:43 mks Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_load.c,v 1.9 2006/01/14 13:36:39 swildner Exp $
28  */
29
30 /*
31  * IP Over ATM Support
32  * -------------------
33  *
34  * Support for running as a loadable kernel module
35  *
36  */
37
38 #ifndef ATM_IP_MODULE
39 #include "opt_atm.h"
40 #endif
41
42 #include <netproto/atm/kern_include.h>
43
44 #include "ipatm.h"
45 #include "ipatm_var.h"
46
47 /*
48  * Global variables
49  */
50 int             ipatm_vccnt = 0;                
51 int             ipatm_vcidle = IPATM_VCIDLE;            
52 int             ipatm_print = 0;
53 u_long          last_map_ipdst = 0;
54 struct ipvcc*   last_map_ipvcc = NULL;
55
56 struct ip_nif   *ipatm_nif_head = NULL;
57
58 struct ipatm_stat       ipatm_stat = {0};
59
60 struct atm_time         ipatm_itimer = {0, 0};  /* VCC idle timer */
61
62 Atm_endpoint    ipatm_endpt = {
63         NULL,
64         ENDPT_IP,
65         ipatm_ioctl,
66         ipatm_getname,
67         ipatm_connected,
68         ipatm_cleared,
69         ipatm_incoming,
70         NULL,
71         NULL,
72         NULL,
73         ipatm_cpcs_data,
74         NULL,
75         NULL,
76         NULL,
77         NULL
78 };
79
80 struct sp_info  ipatm_vcpool = {
81         "ipatm vcc pool",               /* si_name */
82         sizeof(struct ipvcc),           /* si_blksiz */
83         10,                             /* si_blkcnt */
84         100                             /* si_maxallow */
85 };
86
87 struct sp_info  ipatm_nifpool = {
88         "ipatm nif pool",               /* si_name */
89         sizeof(struct ip_nif),          /* si_blksiz */
90         5,                              /* si_blkcnt */
91         52                              /* si_maxallow */
92 };
93
94
95 /*
96  * Local functions
97  */
98 static int      ipatm_start (void);
99 static int      ipatm_stop (void);
100
101
102 /*
103  * Local variables
104  */
105 static struct atm_ncm   ipatm_ncm = {
106         NULL,
107         AF_INET,
108         ipatm_ifoutput,
109         ipatm_nifstat
110 };
111
112 static struct ipatm_listener {
113         Atm_attributes  attr;
114         Atm_connection  *conn;
115 } ipatm_listeners[] = {
116 {
117         {       NULL,                   /* nif */
118                 CMAPI_CPCS,             /* api */
119                 0,                      /* api_init */
120                 0,                      /* headin */
121                 0,                      /* headout */
122                 {                       /* aal */
123                         T_ATM_PRESENT,
124                         ATM_AAL5
125                 },
126                 {                       /* traffic */
127                         T_ATM_PRESENT,
128                         {
129                                 {
130                                         T_ATM_ABSENT,
131                                         0,
132                                         T_ATM_ABSENT,
133                                         T_ATM_ABSENT,
134                                         T_ATM_ABSENT,
135                                         T_ATM_ABSENT,
136                                         T_NO
137                                 },
138                                 {
139                                         T_ATM_ABSENT,
140                                         0,
141                                         T_ATM_ABSENT,
142                                         T_ATM_ABSENT,
143                                         T_ATM_ABSENT,
144                                         T_ATM_ABSENT,
145                                         T_NO
146                                 },
147                                 T_YES
148                         },
149                 },
150                 {                       /* bearer */
151                         T_ATM_ANY
152                 },
153                 {                       /* bhli */
154                         T_ATM_ABSENT
155                 },
156                 {                       /* blli */
157                         T_ATM_PRESENT,
158                         T_ATM_ABSENT,
159                         {
160                                 {
161                                         T_ATM_SIMPLE_ID,
162                                 },
163                                 {
164                                         T_ATM_ABSENT
165                                 }
166                         }
167                 },
168                 {                       /* llc */
169                         T_ATM_PRESENT,
170                         {
171                                 T_ATM_LLC_SHARING,
172                                 IPATM_LLC_LEN,
173                                 IPATM_LLC_HDR
174                         }
175                 },
176                 {                       /* called */
177                         T_ATM_ANY
178                 },
179                 {                       /* calling */
180                         T_ATM_ANY
181                 },
182                 {                       /* qos */
183                         T_ATM_PRESENT,
184                         {
185                                 T_ATM_NETWORK_CODING,
186                                 {
187                                         T_ATM_QOS_CLASS_0,
188                                 },
189                                 {
190                                         T_ATM_QOS_CLASS_0
191                                 }
192                         }
193                 },
194                 {                       /* transit */
195                         T_ATM_ANY
196                 },
197                 {                       /* cause */
198                         T_ATM_ABSENT
199                 },
200         },
201         NULL
202 },
203 {
204         {       NULL,                   /* nif */
205                 CMAPI_CPCS,             /* api */
206                 0,                      /* api_init */
207                 0,                      /* headin */
208                 0,                      /* headout */
209                 {                       /* aal */
210                         T_ATM_PRESENT,
211                         ATM_AAL5
212                 },
213                 {                       /* traffic */
214                         T_ATM_PRESENT,
215                         {
216                                 {
217                                         T_ATM_ABSENT,
218                                         0,
219                                         T_ATM_ABSENT,
220                                         T_ATM_ABSENT,
221                                         T_ATM_ABSENT,
222                                         T_ATM_ABSENT,
223                                         T_NO
224                                 },
225                                 {
226                                         T_ATM_ABSENT,
227                                         0,
228                                         T_ATM_ABSENT,
229                                         T_ATM_ABSENT,
230                                         T_ATM_ABSENT,
231                                         T_ATM_ABSENT,
232                                         T_NO
233                                 },
234                                 T_YES
235                         },
236                 },
237                 {                       /* bearer */
238                         T_ATM_ANY
239                 },
240                 {                       /* bhli */
241                         T_ATM_ABSENT
242                 },
243                 {                       /* blli */
244                         T_ATM_ABSENT,
245                         T_ATM_ABSENT
246                 },
247                 {                       /* llc */
248                         T_ATM_ABSENT
249                 },
250                 {                       /* called */
251                         T_ATM_ANY
252                 },
253                 {                       /* calling */
254                         T_ATM_ANY
255                 },
256                 {                       /* qos */
257                         T_ATM_PRESENT,
258                         {
259                                 T_ATM_NETWORK_CODING,
260                                 {
261                                         T_ATM_QOS_CLASS_0,
262                                 },
263                                 {
264                                         T_ATM_QOS_CLASS_0
265                                 }
266                         }
267                 },
268                 {                       /* transit */
269                         T_ATM_ANY
270                 },
271                 {                       /* cause */
272                         T_ATM_ABSENT
273                 },
274         },
275         NULL
276 },
277 {
278         {       NULL,                   /* nif */
279                 CMAPI_CPCS,             /* api */
280                 0,                      /* api_init */
281                 0,                      /* headin */
282                 0,                      /* headout */
283                 {                       /* aal */
284                         T_ATM_PRESENT,
285                         ATM_AAL3_4
286                 },
287                 {                       /* traffic */
288                         T_ATM_PRESENT,
289                         {
290                                 {
291                                         T_ATM_ABSENT,
292                                         0,
293                                         T_ATM_ABSENT,
294                                         T_ATM_ABSENT,
295                                         T_ATM_ABSENT,
296                                         T_ATM_ABSENT,
297                                         T_NO
298                                 },
299                                 {
300                                         T_ATM_ABSENT,
301                                         0,
302                                         T_ATM_ABSENT,
303                                         T_ATM_ABSENT,
304                                         T_ATM_ABSENT,
305                                         T_ATM_ABSENT,
306                                         T_NO
307                                 },
308                                 T_YES
309                         },
310                 },
311                 {                       /* bearer */
312                         T_ATM_ANY
313                 },
314                 {                       /* bhli */
315                         T_ATM_ABSENT
316                 },
317                 {                       /* blli */
318                         T_ATM_ABSENT,
319                         T_ATM_ABSENT
320                 },
321                 {                       /* llc */
322                         T_ATM_ABSENT
323                 },
324                 {                       /* called */
325                         T_ATM_ANY
326                 },
327                 {                       /* calling */
328                         T_ATM_ANY
329                 },
330                 {                       /* qos */
331                         T_ATM_PRESENT,
332                         {
333                                 T_ATM_NETWORK_CODING,
334                                 {
335                                         T_ATM_QOS_CLASS_0,
336                                 },
337                                 {
338                                         T_ATM_QOS_CLASS_0
339                                 }
340                         }
341                 },
342                 {                       /* transit */
343                         T_ATM_ANY
344                 },
345                 {                       /* cause */
346                         T_ATM_ABSENT
347                 },
348         },
349         NULL
350 },
351 };
352
353 static struct t_atm_cause       ipatm_cause = {
354         T_ATM_ITU_CODING,
355         T_ATM_LOC_USER,
356         T_ATM_CAUSE_UNSPECIFIED_NORMAL,
357         {0, 0, 0, 0}
358 };
359
360
361 /*
362  * Initialize ipatm processing
363  * 
364  * This will be called during module loading.  We'll just register
365  * ourselves and wait for the packets to start flying.
366  *
367  * Arguments:
368  *      none
369  *
370  * Returns:
371  *      0       startup was successful 
372  *      errno   startup failed - reason indicated
373  *
374  */
375 static int
376 ipatm_start(void)
377 {
378         struct atm_pif  *pip;
379         struct atm_nif  *nip;
380         int     err, i;
381
382         /*
383          * Verify software version
384          */
385         if (atm_version != ATM_VERSION) {
386                 log(LOG_ERR, "version mismatch: ipatm=%d.%d kernel=%d.%d\n",
387                         ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
388                         ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
389                 return (EINVAL);
390         }
391
392         /*
393          * Register ourselves as a network convergence module
394          */
395         err = atm_netconv_register(&ipatm_ncm);
396         if (err)
397                 goto done;
398
399         /*
400          * Register ourselves as an ATM endpoint
401          */
402         err = atm_endpoint_register(&ipatm_endpt);
403         if (err)
404                 goto done;
405
406         /*
407          * Get current system configuration
408          */
409         crit_enter();
410         for (pip = atm_interface_head; pip; pip = pip->pif_next) {
411                 /*
412                  * Process each network interface
413                  */
414                 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
415                         struct ifnet    *ifp = (struct ifnet *)nip;
416                         struct in_ifaddr        *ia;
417
418                         /*
419                          * Attach interface
420                          */
421                         err = ipatm_nifstat(NCM_ATTACH, nip, 0);
422                         if (err) {
423                                 crit_exit();
424                                 goto done;
425                         }
426
427                         /*
428                          * If IP address has been set, register it
429                          */
430                         TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
431                                 if (ia->ia_ifp == ifp)
432                                         break;
433                         }
434                         if (ia) {
435                                 err = ipatm_nifstat(NCM_SETADDR, nip, (int)ia);
436                                 if (err) {
437                                         crit_exit();
438                                         goto done;
439                                 }
440                         }
441                 }
442         }
443         crit_exit();
444
445         /*
446          * Fill in union fields
447          */
448         ipatm_aal5llc.aal.v.aal5.forward_max_SDU_size =
449                 ATM_NIF_MTU + IPATM_LLC_LEN;
450         ipatm_aal5llc.aal.v.aal5.backward_max_SDU_size =
451                 ATM_NIF_MTU + IPATM_LLC_LEN;
452         ipatm_aal5llc.aal.v.aal5.SSCS_type = T_ATM_NULL;
453         ipatm_aal5llc.blli.v.layer_2_protocol.ID.simple_ID = T_ATM_BLLI2_I8802;
454
455         ipatm_aal5null.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
456         ipatm_aal5null.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
457         ipatm_aal5null.aal.v.aal5.SSCS_type = T_ATM_NULL;
458
459         ipatm_aal4null.aal.v.aal4.forward_max_SDU_size = ATM_NIF_MTU;
460         ipatm_aal4null.aal.v.aal4.backward_max_SDU_size = ATM_NIF_MTU;
461         ipatm_aal4null.aal.v.aal4.SSCS_type = T_ATM_NULL;
462         ipatm_aal4null.aal.v.aal4.mid_low = 0;
463         ipatm_aal4null.aal.v.aal4.mid_high = 1023;
464
465         /*
466          * Listen for incoming calls
467          */
468         for (i = 0;
469              i < (sizeof(ipatm_listeners) / sizeof(struct ipatm_listener));
470              i++) {
471                 struct attr_aal *aalp = &ipatm_listeners[i].attr.aal;
472                 int     maxsdu = ATM_NIF_MTU;
473
474                 /*
475                  * Fill in union fields
476                  */
477                 if (ipatm_listeners[i].attr.blli.tag_l2 == T_ATM_PRESENT) {
478                         struct t_atm_blli *bp = &ipatm_listeners[i].attr.blli.v;
479
480                         bp->layer_2_protocol.ID.simple_ID = T_ATM_BLLI2_I8802;
481                         maxsdu += IPATM_LLC_LEN;
482                 }
483                 if (aalp->type == ATM_AAL5) {
484                         aalp->v.aal5.forward_max_SDU_size = maxsdu;
485                         aalp->v.aal5.backward_max_SDU_size = maxsdu;
486                         aalp->v.aal5.SSCS_type = T_ATM_NULL;
487                 } else {
488                         aalp->v.aal4.forward_max_SDU_size = maxsdu;
489                         aalp->v.aal4.backward_max_SDU_size = maxsdu;
490                         aalp->v.aal4.SSCS_type = T_ATM_NULL;
491                         aalp->v.aal4.mid_low = 0;
492                         aalp->v.aal4.mid_high = 1023;
493                 }
494
495                 /*
496                  * Now start listening
497                  */
498                 if ((err = atm_cm_listen(&ipatm_endpt, (void *)i,
499                                 &ipatm_listeners[i].attr,
500                                 &ipatm_listeners[i].conn)) != 0)
501                         goto done;
502         }
503
504         /*
505          * Start background VCC idle timer
506          */
507         atm_timeout(&ipatm_itimer, IPATM_IDLE_TIME, ipatm_itimeout);
508
509 done:
510         return (err);
511 }
512
513
514 /*
515  * Halt ipatm processing 
516  * 
517  * This will be called just prior to unloading the module from
518  * memory.  All IP VCCs must be terminated before the protocol can 
519  * be shutdown.
520  *
521  * Arguments:
522  *      none
523  *
524  * Returns:
525  *      0       shutdown was successful 
526  *      errno   shutdown failed - reason indicated
527  *
528  */
529 static int
530 ipatm_stop(void)
531 {
532         struct ip_nif   *inp;
533         int     err = 0, i;
534
535         /*
536          * Any VCCs still open??
537          */
538         crit_enter();
539         if (ipatm_vccnt) {
540                 /* Yes, can't stop now */
541                 err = EBUSY;
542                 goto done;
543         }
544
545         /*
546          * Kill VCC idle timer
547          */
548         atm_untimeout(&ipatm_itimer);
549
550         /*
551          * Stop listening for incoming calls
552          */
553         for (i = 0;
554              i < (sizeof(ipatm_listeners) / sizeof(struct ipatm_listener));
555              i++) {
556                 if (ipatm_listeners[i].conn != NULL) {
557                         atm_cm_release(ipatm_listeners[i].conn, &ipatm_cause);
558                 }
559         }
560
561         /*
562          * Detach all our interfaces
563          */
564         while ((inp = ipatm_nif_head) != NULL) {
565                 ipatm_nifstat(NCM_DETACH, inp->inf_nif, 0);
566         }
567         
568         /*
569          * De-register from system
570          */
571         atm_netconv_deregister(&ipatm_ncm);
572         atm_endpoint_deregister(&ipatm_endpt);
573
574         /*
575          * Free up our storage pools
576          */
577         atm_release_pool(&ipatm_vcpool);
578         atm_release_pool(&ipatm_nifpool);
579
580 done:
581         crit_exit();
582         return (err);
583 }
584
585
586 #ifdef ATM_IP_MODULE 
587 /*
588  *******************************************************************
589  *
590  * Loadable Module Support
591  *
592  *******************************************************************
593  */
594 static int      ipatm_doload (void);
595 static int      ipatm_dounload (void);
596
597 /*
598  * Generic module load processing
599  * 
600  * This function is called by an OS-specific function when this
601  * module is being loaded.
602  *
603  * Arguments:
604  *      none
605  *
606  * Returns:
607  *      0       load was successful 
608  *      errno   load failed - reason indicated
609  *
610  */
611 static int
612 ipatm_doload(void)
613 {
614         int     err = 0;
615
616         /*
617          * Start us up
618          */
619         err = ipatm_start();
620         if (err)
621                 /* Problems, clean up */
622                 ipatm_stop();
623
624         return (err);
625 }
626
627
628 /*
629  * Generic module unload processing
630  * 
631  * This function is called by an OS-specific function when this
632  * module is being unloaded.
633  *
634  * Arguments:
635  *      none
636  *
637  * Returns:
638  *      0       unload was successful 
639  *      errno   unload failed - reason indicated
640  *
641  */
642 static int
643 ipatm_dounload(void)
644 {
645         int     err = 0;
646
647         /*
648          * OK, try to clean up our mess
649          */
650         err = ipatm_stop();
651
652         return (err);
653 }
654
655 #include <sys/exec.h>
656 #include <sys/sysent.h>
657 #include <sys/lkm.h>
658
659 /*
660  * Loadable miscellaneous module description
661  */
662 MOD_MISC(ipatm);
663
664
665 /*
666  * Loadable module support "load" entry point
667  * 
668  * This is the routine called by the lkm driver whenever the
669  * modload(1) command is issued for this module.
670  *
671  * Arguments:
672  *      lkmtp   pointer to lkm drivers's structure
673  *      cmd     lkm command code
674  *
675  * Returns:
676  *      0       command was successful 
677  *      errno   command failed - reason indicated
678  *
679  */
680 static int
681 ipatm_load(struct lkm_table *lkmtp, int cmd)
682 {
683         return(ipatm_doload());
684 }
685
686
687 /*
688  * Loadable module support "unload" entry point
689  * 
690  * This is the routine called by the lkm driver whenever the
691  * modunload(1) command is issued for this module.
692  *
693  * Arguments:
694  *      lkmtp   pointer to lkm drivers's structure
695  *      cmd     lkm command code
696  *
697  * Returns:
698  *      0       command was successful 
699  *      errno   command failed - reason indicated
700  *
701  */
702 static int
703 ipatm_unload(struct lkm_table *lkmtp, int cmd)
704 {
705         return(ipatm_dounload());
706 }
707
708
709 /*
710  * Loadable module support entry point
711  * 
712  * This is the routine called by the lkm driver for all loadable module
713  * functions for this driver.  This routine name must be specified
714  * on the modload(1) command.  This routine will be called whenever the
715  * modload(1), modunload(1) or modstat(1) commands are issued for this
716  * module.
717  *
718  * Arguments:
719  *      lkmtp   pointer to lkm drivers's structure
720  *      cmd     lkm command code
721  *      ver     lkm version
722  *
723  * Returns:
724  *      0       command was successful 
725  *      errno   command failed - reason indicated
726  *
727  */
728 int
729 ipatm_mod(struct lkm_table *lkmtp, int cmd, int ver)
730 {
731         MOD_DISPATCH(ipatm, lkmtp, cmd, ver,
732                 ipatm_load, ipatm_unload, lkm_nullcmd);
733 }
734
735 #else   /* !ATM_IP_MODULE */
736
737 /*
738  *******************************************************************
739  *
740  * Kernel Compiled Module Support
741  *
742  *******************************************************************
743  */
744 static void     ipatm_doload (void *);
745
746 SYSINIT(atmipatm, SI_SUB_PROTO_END, SI_ORDER_ANY, ipatm_doload, NULL)
747
748 /*
749  * Kernel initialization
750  * 
751  * Arguments:
752  *      arg     Not used
753  *
754  * Returns:
755  *      none
756  *
757  */
758 static void
759 ipatm_doload(void *arg)
760 {
761         int     err = 0;
762
763         /*
764          * Start us up
765          */
766         err = ipatm_start();
767         if (err) {
768                 /* Problems, clean up */
769                 ipatm_stop();
770
771                 log(LOG_ERR, "IP over ATM unable to initialize (%d)!!\n", err);
772         }
773         return;
774 }
775 #endif  /* ATM_IP_MODULE */
776