]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/atm/scspd/scsp_subr.c
This commit was generated by cvs2svn to compensate for changes in r161818,
[FreeBSD/FreeBSD.git] / usr.sbin / atm / scspd / scsp_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$
27  *
28  */
29
30
31 /*
32  * Server Cache Synchronization Protocol (SCSP) Support
33  * ----------------------------------------------------
34  *
35  * SCSP subroutines
36  *
37  */
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
42 #include <net/if.h>
43 #include <netinet/in.h>
44 #include <netatm/port.h> 
45 #include <netatm/queue.h> 
46 #include <netatm/atm.h>
47 #include <netatm/atm_if.h>
48 #include <netatm/atm_sap.h>
49 #include <netatm/atm_sigmgr.h>
50 #include <netatm/atm_sys.h>
51 #include <netatm/atm_ioctl.h>
52 #include <netatm/uni/unisig_var.h>
53
54 #include <errno.h>
55 #include <libatm.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <syslog.h>
60 #include <unistd.h>
61
62 #include "scsp_msg.h"
63 #include "scsp_if.h"
64 #include "scsp_var.h"
65
66 #ifndef lint
67 __RCSID("@(#) $FreeBSD$");
68 #endif
69
70
71 /*
72  * Hash an SCSP cache key
73  *
74  * Arguments:
75  *      ckp     pointer to an SCSP cache key structure
76  *
77  * Returns:
78  *      hashed value
79  *
80  */
81 int
82 scsp_hash(ckp)
83         Scsp_ckey       *ckp;
84 {
85         int     i, j, h;
86
87         /*
88          * Turn cache key into a positive integer
89          */
90         h = 0;
91         for (i = ckp->key_len-1, j = 0;
92                         i > 0 && j < sizeof(int);
93                         i--, j++)
94                 h = (h << 8) + ckp->key[i];
95         h = abs(h);
96
97         /*
98          * Return the hashed value
99          */
100         return(h % SCSP_HASHSZ);
101 }
102
103
104 /*
105  * Compare two SCSP IDs
106  *
107  * Arguments:
108  *      id1p    pointer to an SCSP ID structure
109  *      id2p    pointer to an SCSP ID structure
110  *
111  * Returns:
112  *      < 0     id1 is less than id2
113  *      0       id1 and id2 are equal
114  *      > 0     id1 is greater than id2
115  *
116  */
117 int
118 scsp_cmp_id(id1p, id2p)
119         Scsp_id *id1p;
120         Scsp_id *id2p;
121 {
122         int     diff, i;
123
124         /*
125          * Compare the two IDs, byte for byte
126          */
127         for (i = 0; i < id1p->id_len && i < id2p->id_len; i++) {
128                 diff = id1p->id[i] - id2p->id[i];
129                 if (diff) {
130                         return(diff);
131                 }
132         }
133
134         /*
135          * IDs are equal.  If lengths differ, the longer ID is
136          * greater than the shorter.
137          */
138         return(id1p->id_len - id2p->id_len);
139 }
140
141
142 /*
143  * Compare two SCSP cache keys
144  *
145  * Arguments:
146  *      ck1p    pointer to an SCSP cache key structure
147  *      ck2p    pointer to an SCSP cache key structure
148  *
149  * Returns:
150  *      < 0     ck1 is less than ck2
151  *      0       ck1 and ck2 are equal
152  *      > 0     ck1 is greater than ck2
153  *
154  */
155 int
156 scsp_cmp_key(ck1p, ck2p)
157         Scsp_ckey       *ck1p;
158         Scsp_ckey       *ck2p;
159 {
160         int     diff, i;
161
162         /*
163          * Compare the two keys, byte for byte
164          */
165         for (i = 0; i < ck1p->key_len && i < ck2p->key_len; i++) {
166                 diff = ck1p->key[i] - ck2p->key[i];
167                 if (diff)
168                         return(diff);
169         }
170
171         /*
172          * Keys are equal.  If lengths differ, the longer key is
173          * greater than the shorter.
174          */
175         return(ck1p->key_len - ck2p->key_len);
176 }
177
178
179 /*
180  * Check whether the host system is an ATMARP server for
181  * the LIS associated with a given interface
182  *
183  * Arguments:
184  *      netif   pointer to the network interface name
185  *
186  * Returns:
187  *      1       host is a server
188  *      0       host is not a server
189  *
190  */
191 int
192 scsp_is_atmarp_server(netif)
193         char    *netif;
194 {
195         int                     rc;
196         size_t buf_len;
197         struct atminfreq        air;
198         struct air_asrv_rsp     *asrv_info;
199
200         /*
201          * Get interface information from the kernel
202          */
203         strcpy(air.air_int_intf, netif);
204         air.air_opcode = AIOCS_INF_ASV;
205         buf_len = do_info_ioctl(&air, sizeof(struct air_asrv_rsp));
206         if ((ssize_t)buf_len == -1)
207                 return(0);
208
209         /*
210          * Check the interface's ATMARP server address
211          */
212         asrv_info = (struct air_asrv_rsp *) air.air_buf_addr;
213         rc = (asrv_info->asp_addr.address_format == T_ATM_ABSENT) &&
214                         (asrv_info->asp_subaddr.address_format ==
215                                 T_ATM_ABSENT);
216         free(asrv_info);
217         return(rc);
218 }
219
220
221 /*
222  * Make a copy of a cache summary entry
223  *
224  * Arguments:
225  *      csep    pointer to CSE entry to copy
226  *
227  * Returns:
228  *      0       copy failed
229  *      else    pointer to new CSE entry
230  *
231  */
232 Scsp_cse *
233 scsp_dup_cse(csep)
234         Scsp_cse        *csep;
235 {
236         Scsp_cse        *dupp;
237
238         /*
239          * Allocate memory for the duplicate
240          */
241         dupp = malloc(sizeof(Scsp_cse));
242         if (dupp == NULL)
243                 scsp_mem_err("scsp_dup_cse: sizeof(Scsp_cse)");
244
245         /*
246          * Copy data to the duplicate
247          */
248         bcopy(csep, dupp, sizeof(Scsp_cse));
249         dupp->sc_next = (Scsp_cse *)0;
250         return(dupp);
251 }
252
253
254 /*
255  * Make a copy of a CSA or CSAS record
256  *
257  * Arguments:
258  *      csap    pointer to CSE entry to copy
259  *
260  * Returns:
261  *      0       copy failed
262  *      else    pointer to new CSA or CSAS record
263  *
264  */
265 Scsp_csa *
266 scsp_dup_csa(csap)
267         Scsp_csa        *csap;
268 {
269         Scsp_csa        *dupp;
270         Scsp_atmarp_csa *adp;
271
272         /*
273          * Allocate memory for the duplicate
274          */
275         dupp = malloc(sizeof(Scsp_csa));
276         if (dupp == NULL)
277                 scsp_mem_err("scsp_dup_csa: sizeof(Scsp_csa)");
278
279         /*
280          * Copy data to the duplicate
281          */
282         bcopy(csap, dupp, sizeof(Scsp_csa));
283         dupp->next = (Scsp_csa *)0;
284
285         /*
286          * Copy protocol-specific data, if it's present
287          */
288         if (csap->atmarp_data) {
289                 adp = malloc(sizeof(Scsp_atmarp_csa));
290                 if (adp == NULL)
291                         scsp_mem_err("scsp_dup_csa: sizeof(Scsp_atmarp_csa)");
292                 bcopy(csap->atmarp_data, adp, sizeof(Scsp_atmarp_csa));
293                 dupp->atmarp_data  = adp;
294         }
295         return(dupp);
296 }
297
298
299 /*
300  * Copy a cache summary entry into a CSAS
301  *
302  * Arguments:
303  *      csep    pointer to CSE entry to copy
304  *
305  * Returns:
306  *      0       copy failed
307  *      else    pointer to CSAS record summarizing the entry
308  *
309  */
310 Scsp_csa *
311 scsp_cse2csas(csep)
312         Scsp_cse        *csep;
313 {
314         Scsp_csa        *csap;
315
316         /*
317          * Allocate memory for the duplicate
318          */
319         csap = calloc(1, sizeof(Scsp_csa));
320         if (csap == NULL)
321                 scsp_mem_err("scsp_cse2csas: sizeof(Scsp_csa)");
322
323         /*
324          * Copy data to the CSAS entry
325          */
326         csap->seq = csep->sc_seq;
327         csap->key = csep->sc_key;
328         csap->oid = csep->sc_oid;
329
330         return(csap);
331 }
332
333
334 /*
335  * Copy an ATMARP cache entry into a cache summary entry
336  *
337  * Arguments:
338  *      aap     pointer to ATMARP cache entry to copy
339  *
340  * Returns:
341  *      0       copy failed
342  *      else    pointer to CSE record summarizing the entry
343  *
344  */
345 Scsp_cse *
346 scsp_atmarp2cse(aap)
347         Scsp_atmarp_msg *aap;
348 {
349         Scsp_cse        *csep;
350
351         /*
352          * Allocate memory for the duplicate
353          */
354         csep = calloc(1, sizeof(Scsp_cse));
355         if (csep == NULL)
356                 scsp_mem_err("scsp_atmarp2cse: sizeof(Scsp_cse)");
357
358         /*
359          * Copy data to the CSE entry
360          */
361         csep->sc_seq = aap->sa_seq;
362         csep->sc_key = aap->sa_key;
363         csep->sc_oid = aap->sa_oid;
364
365         return(csep);
366 }
367
368
369 /*
370  * Clean up a DCS block.  This routine is called to clear out any
371  * lingering state information when the CA FSM reverts to an 'earlier'
372  * state (Down or Master/Slave Negotiation).
373  *
374  * Arguments:
375  *      dcsp    pointer to a DCS control block for the neighbor
376  *
377  * Returns:
378  *      none
379  *
380  */
381 void
382 scsp_dcs_cleanup(dcsp)
383         Scsp_dcs        *dcsp;
384 {
385         Scsp_cse        *csep, *ncsep;
386         Scsp_csa        *csap, *next_csap;
387         Scsp_csu_rexmt  *rxp, *rx_next;
388
389         /*
390          * Free any CSAS entries waiting to be sent
391          */
392         for (csep = dcsp->sd_ca_csas; csep; csep = ncsep) {
393                 ncsep = csep->sc_next;
394                 UNLINK(csep, Scsp_cse, dcsp->sd_ca_csas, sc_next);
395                 free(csep);
396         }
397
398         /*
399          * Free any entries on the CRL
400          */
401         for (csap = dcsp->sd_crl; csap; csap = next_csap) {
402                 next_csap = csap->next;
403                 UNLINK(csap, Scsp_csa, dcsp->sd_crl, next);
404                 SCSP_FREE_CSA(csap);
405         }
406
407         /*
408          * Free any saved CA message and cancel the CA
409          * retransmission timer
410          */
411         if (dcsp->sd_ca_rexmt_msg) {
412                 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
413                 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
414         }
415         HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
416
417         /*
418          * Free any saved CSU Solicit message and cancel the CSUS
419          * retransmission timer
420          */
421         if (dcsp->sd_csus_rexmt_msg) {
422                 scsp_free_msg(dcsp->sd_csus_rexmt_msg);
423                 dcsp->sd_csus_rexmt_msg = (Scsp_msg *)0;
424         }
425         HARP_CANCEL(&dcsp->sd_csus_rexmt_t);
426
427         /*
428          * Free any entries on the CSU Request retransmission queue
429          */
430         for (rxp = dcsp->sd_csu_rexmt; rxp; rxp = rx_next) {
431                 rx_next = rxp->sr_next;
432                 HARP_CANCEL(&rxp->sr_t);
433                 for (csap = rxp->sr_csa; csap; csap = next_csap) {
434                         next_csap = csap->next;
435                         SCSP_FREE_CSA(csap);
436                 }
437                 UNLINK(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt,
438                                 sr_next);
439                 free(rxp);
440         }
441 }
442
443
444 /*
445  * Delete an SCSP DCS block and any associated information
446  *
447  * Arguments:
448  *      dcsp    pointer to a DCS control block to delete
449  *
450  * Returns:
451  *      none
452  *
453  */
454 void
455 scsp_dcs_delete(dcsp)
456         Scsp_dcs        *dcsp;
457 {
458         Scsp_cse        *csep, *next_cse;
459         Scsp_csu_rexmt  *rxp, *next_rxp;
460         Scsp_csa        *csap, *next_csa;
461
462         /*
463          * Cancel any pending DCS timers
464          */
465         HARP_CANCEL(&dcsp->sd_open_t);
466         HARP_CANCEL(&dcsp->sd_hello_h_t);
467         HARP_CANCEL(&dcsp->sd_hello_rcv_t);
468         HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
469         HARP_CANCEL(&dcsp->sd_csus_rexmt_t);
470
471         /*
472          * Unlink the DCS block from the server block
473          */
474         UNLINK(dcsp, Scsp_dcs, dcsp->sd_server->ss_dcs, sd_next);
475
476         /*
477          * Close the VCC to the DCS, if one is open
478          */
479         if (dcsp->sd_sock != -1) {
480                 (void)close(dcsp->sd_sock);
481         }
482
483         /*
484          * Free any saved CA message
485          */
486         if (dcsp->sd_ca_rexmt_msg) {
487                 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
488         }
489
490         /*
491          * Free any pending CSAs waiting for cache alignment
492          */
493         for (csep = dcsp->sd_ca_csas; csep; csep = next_cse) {
494                 next_cse = csep->sc_next;
495                 free(csep);
496         }
497
498         /*
499          * Free anything on the cache request list
500          */
501         for (csap = dcsp->sd_crl; csap; csap = next_csa) {
502                 next_csa = csap->next;
503                 SCSP_FREE_CSA(csap);
504         }
505
506         /*
507          * Free any saved CSUS message
508          */
509         if (dcsp->sd_csus_rexmt_msg) {
510                 scsp_free_msg(dcsp->sd_csus_rexmt_msg);
511         }
512
513         /*
514          * Free anything on the CSU Request retransmit queue
515          */
516         for (rxp = dcsp->sd_csu_rexmt; rxp; rxp = next_rxp) {
517                 /*
518                  * Cancel the retransmit timer
519                  */
520                 HARP_CANCEL(&rxp->sr_t);
521
522                 /*
523                  * Free the CSAs to be retransmitted
524                  */
525                 for (csap = rxp->sr_csa; csap; csap = next_csa) {
526                         next_csa = csap->next;
527                         SCSP_FREE_CSA(csap);
528                 }
529
530                 /*
531                  * Free the CSU Req retransmission control block
532                  */
533                 next_rxp = rxp->sr_next;
534                 free(rxp);
535         }
536
537         /*
538          * Free the DCS block
539          */
540         free(dcsp);
541 }
542
543
544 /*
545  * Shut down a server.  This routine is called when a connection to
546  * a server is lost.  It will clear the server's state without deleting
547  * the server.
548  *
549  * Arguments:
550  *      ssp     pointer to a server control block
551  *
552  * Returns:
553  *      none
554  *
555  */
556 void
557 scsp_server_shutdown(ssp)
558         Scsp_server     *ssp;
559 {
560         int             i;
561         Scsp_dcs        *dcsp;
562         Scsp_cse        *csep;
563
564         /*
565          * Trace the shutdown
566          */
567         if (scsp_trace_mode & (SCSP_TRACE_IF_MSG | SCSP_TRACE_CFSM)) {
568                 scsp_trace("Server %s being shut down\n",
569                                 ssp->ss_name);
570         }
571
572         /*
573          * Terminate up all the DCS connections and clean
574          * up the control blocks
575          */
576         for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
577                 if (dcsp->sd_sock != -1) {
578                         (void)close(dcsp->sd_sock);
579                         dcsp->sd_sock = -1;
580                 }
581                 HARP_CANCEL(&dcsp->sd_open_t);
582                 HARP_CANCEL(&dcsp->sd_hello_h_t);
583                 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
584                 scsp_dcs_cleanup(dcsp);
585                 dcsp->sd_hello_state = SCSP_HFSM_DOWN;
586                 dcsp->sd_ca_state = SCSP_CAFSM_DOWN;
587                 dcsp->sd_client_state = SCSP_CIFSM_NULL;
588         }
589
590         /*
591          * Clean up the server control block
592          */
593         if (ssp->ss_sock != -1) {
594                 (void)close(ssp->ss_sock);
595                 ssp->ss_sock = -1;
596         }
597         if (ssp->ss_dcs_lsock != -1) {
598                 (void)close(ssp->ss_dcs_lsock);
599                 ssp->ss_dcs_lsock = -1;
600         }
601         ssp->ss_state = SCSP_SS_NULL;
602
603         /*
604          * Free the entries in the server's summary cache
605          */
606         for (i = 0; i < SCSP_HASHSZ; i++) {
607                 while (ssp->ss_cache[i]) {
608                         csep = ssp->ss_cache[i];
609                         UNLINK(csep, Scsp_cse, ssp->ss_cache[i],
610                                         sc_next);
611                         free(csep);
612                 }
613         }
614 }
615
616
617 /*
618  * Delete an SCSP server block and any associated information
619  *
620  * Arguments:
621  *      ssp     pointer to a server control block to delete
622  *
623  * Returns:
624  *      none
625  *
626  */
627 void
628 scsp_server_delete(ssp)
629         Scsp_server     *ssp;
630 {
631         int             i;
632         Scsp_dcs        *dcsp, *next_dcs;
633         Scsp_cse        *csep, *next_cse;
634
635         /*
636          * Unlink the server block from the chain
637          */
638         UNLINK(ssp, Scsp_server, scsp_server_head, ss_next);
639
640         /*
641          * Free the DCS blocks associated with the server
642          */
643         for (dcsp = ssp->ss_dcs; dcsp; dcsp = next_dcs) {
644                 next_dcs = dcsp->sd_next;
645                 scsp_dcs_delete(dcsp);
646         }
647
648         /*
649          * Free the entries in the server's summary cache
650          */
651         for (i = 0; i < SCSP_HASHSZ; i++) {
652                 for (csep = ssp->ss_cache[i]; csep; csep = next_cse) {
653                         next_cse = csep->sc_next;
654                         free(csep);
655                 }
656         }
657
658         /*
659          * Free the server block
660          */
661         free(ssp->ss_name);
662         free(ssp);
663 }
664
665
666 /*
667  * Get informtion about a server from the kernel
668  *
669  * Arguments:
670  *      ssp     pointer to the server block
671  *
672  * Returns:
673  *      0       server info is OK
674  *      errno   server is not ready
675  *
676  */
677 int
678 scsp_get_server_info(ssp)
679         Scsp_server     *ssp;
680 {
681         int                     i, mtu, rc, sel;
682         size_t len;
683         struct atminfreq        air;
684         struct air_netif_rsp    *netif_rsp = (struct air_netif_rsp *)0;
685         struct air_int_rsp      *intf_rsp = (struct air_int_rsp *)0;
686         struct air_cfg_rsp      *cfg_rsp = (struct air_cfg_rsp *)0;
687         struct sockaddr_in      *ip_addr;
688         Atm_addr_nsap           *anp;
689
690         /*
691          * Make sure we're the server for the interface
692          */
693         if (!scsp_is_atmarp_server(ssp->ss_intf)) {
694                 rc = EINVAL;
695                 goto server_info_done;
696         }
697
698         /*
699          * Get the IP address and physical interface name
700          * associated with the network interface
701          */
702         bzero(&air, sizeof(struct atminfreq));
703         air.air_opcode = AIOCS_INF_NIF;
704         strcpy(air.air_netif_intf, ssp->ss_intf);
705         len = do_info_ioctl(&air, sizeof(struct air_netif_rsp));
706         if ((ssize_t)len == -1 || len == 0) {
707                 rc = EIO;
708                 goto server_info_done;
709         }
710         netif_rsp = (struct air_netif_rsp *)air.air_buf_addr;
711
712         ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr;
713         if (ip_addr->sin_family != AF_INET ||
714                         ip_addr->sin_addr.s_addr == 0) {
715                 rc = EADDRNOTAVAIL;
716                 goto server_info_done;
717         }
718
719         /*
720          * Get the MTU for the network interface
721          */
722         mtu = get_mtu(ssp->ss_intf);
723         if (mtu < 0) {
724                 rc = EIO;
725                 goto server_info_done;
726         }
727
728         /*
729          * Get the ATM address associated with the
730          * physical interface
731          */
732         bzero(&air, sizeof(struct atminfreq));
733         air.air_opcode = AIOCS_INF_INT;
734         strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
735         len = do_info_ioctl(&air, sizeof(struct air_int_rsp));
736         if ((ssize_t)len == -1 || len == 0) {
737                 rc = EIO;
738                 goto server_info_done;
739         }
740         intf_rsp = (struct air_int_rsp *)air.air_buf_addr;
741
742         /*
743          * Make sure we're running UNI signalling
744          */
745         if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 &&
746                         intf_rsp->anp_sig_proto != ATM_SIG_UNI31 &&
747                         intf_rsp->anp_sig_proto != ATM_SIG_UNI40) {
748                 rc = EINVAL;
749                 goto server_info_done;
750         }
751
752         /*
753          * Check the physical interface's state
754          */
755         if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
756                 rc = EHOSTDOWN;
757                 goto server_info_done;
758         }
759
760         /*
761          * Make sure the interface's address is valid
762          */
763         if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
764                         !(intf_rsp->anp_addr.address_format ==
765                                 T_ATM_E164_ADDR &&
766                         intf_rsp->anp_subaddr.address_format ==
767                                 T_ATM_ENDSYS_ADDR)) {
768                 rc = EINVAL;
769                 goto server_info_done;
770         }
771
772         /*
773          * Find the selector byte value for the interface
774          */
775         for (i=0; i<strlen(ssp->ss_intf); i++) {
776                 if (ssp->ss_intf[i] >= '0' &&
777                                 ssp->ss_intf[i] <= '9')
778                         break;
779         }
780         sel = atoi(&ssp->ss_intf[i]);
781
782         /*
783          * Get configuration information associated with the
784          * physical interface
785          */
786         bzero(&air, sizeof(struct atminfreq));
787         air.air_opcode = AIOCS_INF_CFG;
788         strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
789         len = do_info_ioctl(&air, sizeof(struct air_cfg_rsp));
790         if ((ssize_t)len == -1 || len == 0) {
791                 rc = EIO;
792                 goto server_info_done;
793         }
794         cfg_rsp = (struct air_cfg_rsp *)air.air_buf_addr;
795
796         /*
797          * Update the server entry
798          */
799         bcopy(&ip_addr->sin_addr, ssp->ss_lsid.id, ssp->ss_id_len);
800         ssp->ss_lsid.id_len = ssp->ss_id_len;
801         ssp->ss_mtu = mtu + 8;
802         ATM_ADDR_COPY(&intf_rsp->anp_addr, &ssp->ss_addr);
803         ATM_ADDR_COPY(&intf_rsp->anp_subaddr, &ssp->ss_subaddr);
804         if (ssp->ss_addr.address_format == T_ATM_ENDSYS_ADDR) {
805                 anp = (Atm_addr_nsap *)ssp->ss_addr.address;
806                 anp->aan_sel = sel;
807         } else if (ssp->ss_addr.address_format == T_ATM_E164_ADDR &&
808                         ssp->ss_subaddr.address_format ==
809                                 T_ATM_ENDSYS_ADDR) {
810                 anp = (Atm_addr_nsap *)ssp->ss_subaddr.address;
811                 anp->aan_sel = sel;
812         }
813         ssp->ss_media = cfg_rsp->acp_cfg.ac_media;
814         rc = 0;
815
816         /*
817          * Free dynamic data
818          */
819 server_info_done:
820         if (netif_rsp)
821                 free(netif_rsp);
822         if (intf_rsp)
823                 free(intf_rsp);
824         if (cfg_rsp)
825                 free(cfg_rsp);
826
827         return(rc);
828 }
829
830
831 /*
832  * Process a CA message
833  *
834  * Arguments:
835  *      dcsp    pointer to a DCS control block for the neighbor
836  *      cap     pointer to the CA part of the received message
837  *
838  * Returns:
839  *      none
840  *
841  */
842 void
843 scsp_process_ca(dcsp, cap)
844         Scsp_dcs        *dcsp;
845         Scsp_ca         *cap;
846 {
847         Scsp_csa        *csap, *next_csap;
848         Scsp_cse        *csep;
849         Scsp_server     *ssp = dcsp->sd_server;
850
851         /*
852          * Process CSAS records from the CA message
853          */
854         for (csap = cap->ca_csa_rec; csap; csap = next_csap) {
855                 next_csap = csap->next;
856                 SCSP_LOOKUP(ssp, &csap->key, csep);
857                 if (!csep || (scsp_cmp_id(&csap->oid,
858                                         &csep->sc_oid) == 0 &&
859                                 csap->seq > csep->sc_seq)) {
860                         /*
861                          * CSAS entry not in cache or more
862                          * up to date than cache, add it to CRL
863                          */
864                         UNLINK(csap, Scsp_csa, cap->ca_csa_rec, next);
865                         LINK2TAIL(csap, Scsp_csa, dcsp->sd_crl, next);
866                 }
867         }
868 }
869
870
871 /*
872  * Process a Cache Response message from a server
873  *
874  * Arguments:
875  *      ssp     pointer to the server block
876  *      smp     pointer to the message
877  *
878  * Returns:
879  *      none
880  *
881  */
882 void
883 scsp_process_cache_rsp(ssp, smp)
884         Scsp_server     *ssp;
885         Scsp_if_msg     *smp;
886 {
887         int             len;
888         Scsp_atmarp_msg *aap;
889         Scsp_cse        *csep;
890
891         /*
892          * Loop through the message, processing each cache entry
893          */
894         len = smp->si_len;
895         len -= sizeof(Scsp_if_msg_hdr);
896         aap = &smp->si_atmarp;
897         while (len > 0) {
898                 switch(smp->si_proto) {
899                 case SCSP_ATMARP_PROTO:
900                         /*
901                          * If we already have an entry with this key,
902                          * delete it
903                          */
904                         SCSP_LOOKUP(ssp, &aap->sa_key, csep);
905                         if (csep) {
906                                 SCSP_DELETE(ssp, csep);
907                                 free(csep);
908                         }
909
910                         /*
911                          * Copy the data from the server to a cache
912                          * summary entry
913                          */
914                         csep = scsp_atmarp2cse(aap);
915
916                         /*
917                          * Point past this entry
918                          */
919                         len -= sizeof(Scsp_atmarp_msg);
920                         aap++;
921                         break;
922                 case SCSP_NHRP_PROTO:
923                 default:
924                         /*
925                          * Not implemented yet
926                          */
927                         return;
928                 }
929
930                 /*
931                  * Add the new summary entry to the cache
932                  */
933                 SCSP_ADD(ssp, csep);
934         }
935 }
936
937
938 /*
939  * Propagate a CSA to all the DCSs in the server group except
940  * the one the CSA was received from
941  *
942  * Arguments:
943  *      dcsp    pointer to a the DCS the CSA came from
944  *      csap    pointer to a the CSA
945  *
946  * Returns:
947  *      0       success
948  *      errno   error encountered
949  *
950  */
951 int
952 scsp_propagate_csa(dcsp, csap)
953         Scsp_dcs        *dcsp;
954         Scsp_csa        *csap;
955 {
956         int             rc, ret_rc = 0;
957         Scsp_server     *ssp = dcsp->sd_server;
958         Scsp_dcs        *dcsp1;
959         Scsp_csa        *csap1;
960
961         /*
962          * Check the hop count in the CSA
963          */
964         if (csap->hops <= 1)
965                 return(0);
966
967         /*
968          * Pass the cache entry on to the server's other DCSs
969          */
970         for (dcsp1 = ssp->ss_dcs; dcsp1; dcsp1 = dcsp1->sd_next) {
971                 /*
972                  * Skip this DCS if it's the one we got
973                  * the entry from
974                  */
975                 if (dcsp1 == dcsp)
976                         continue;
977
978                 /*
979                  * Copy the  CSA
980                  */
981                 csap1 = scsp_dup_csa(csap);
982
983                 /*
984                  * Decrement the hop count
985                  */
986                 csap1->hops--;
987
988                 /*
989                  * Send the copy of the CSA to the CA FSM for the DCS
990                  */
991                 rc = scsp_cafsm(dcsp1, SCSP_CAFSM_CACHE_UPD,
992                                 (void *) csap1);
993                 if (rc)
994                         ret_rc = rc;
995         }
996
997         return(ret_rc);
998 }
999
1000
1001 /*
1002  * Update SCSP's cache given a CSA or CSAS
1003  *
1004  * Arguments:
1005  *      dcsp    pointer to a DCS 
1006  *      csap    pointer to a CSA
1007  *
1008  * Returns:
1009  *      none
1010  *
1011  */
1012 void
1013 scsp_update_cache(dcsp, csap)
1014         Scsp_dcs        *dcsp;
1015         Scsp_csa        *csap;
1016 {
1017         Scsp_cse        *csep;
1018
1019         /*
1020          * Check whether we already have this in the cache
1021          */
1022         SCSP_LOOKUP(dcsp->sd_server, &csap->key, csep);
1023
1024         /*
1025          * If we don't already have it and it's not being deleted,
1026          * build a new cache summary entry
1027          */
1028         if (!csep && !csap->null) {
1029                 /*
1030                  * Get memory for a new entry
1031                  */
1032                 csep = calloc(1, sizeof(Scsp_cse));
1033                 if (csep == NULL)
1034                         scsp_mem_err("scsp_update_cache: sizeof(Scsp_cse)");
1035
1036                 /*
1037                  * Fill out the new cache summary entry
1038                  */
1039                 csep->sc_seq = csap->seq;
1040                 csep->sc_key = csap->key;
1041                 csep->sc_oid = csap->oid;
1042
1043                 /*
1044                  * Add the new entry to the cache
1045                  */
1046                 SCSP_ADD(dcsp->sd_server, csep);
1047         } 
1048
1049         /*
1050          * Update or delete the entry
1051          */
1052         if (csap->null) {
1053                 /*
1054                  * The null flag is set--delete the entry
1055                  */
1056                 if (csep) {
1057                         SCSP_DELETE(dcsp->sd_server, csep);
1058                         free(csep);
1059                 }
1060         } else {
1061                 /*
1062                  * Update the existing entry
1063                  */
1064                 csep->sc_seq = csap->seq;
1065                 csep->sc_oid = csap->oid;
1066         }
1067 }
1068
1069
1070 /*
1071  * Reconfigure SCSP
1072  *
1073  * Called as the result of a SIGHUP interrupt.  Reread the
1074  * configuration file and solicit the cache from the server.
1075  *
1076  * Arguments:
1077  *      none
1078  *
1079  * Returns:
1080  *      none
1081  *
1082  */
1083 void
1084 scsp_reconfigure()
1085 {
1086         int             rc;
1087         Scsp_server     *ssp;
1088
1089         /*
1090          * Log a message saying we're reconfiguring
1091          */
1092         scsp_log(LOG_ERR, "Reconfiguring ...");
1093
1094         /*
1095          * Re-read the configuration file
1096          */
1097         rc = scsp_config(scsp_config_file);
1098         if (rc) {
1099                 scsp_log(LOG_ERR, "Found %d error%s in configuration file",
1100                                 rc, ((rc == 1) ? "" : "s"));
1101                 exit(1);
1102         }
1103
1104         /*
1105          * If a connection to a server is open, get the cache from
1106          * the server
1107          */
1108         for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
1109                 if (ssp->ss_sock != -1) {
1110                         rc = scsp_send_cache_ind(ssp);
1111                 }
1112         }
1113 }