MFC: following 2 commits:
[dragonfly.git] / usr.sbin / atm / scspd / scsp_subr.c
blob95b85356496e863ea2b0a18931e2312008a33d4f
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_subr.c,v 1.3 1999/08/28 01:15:34 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_subr.c,v 1.4 2004/12/18 22:48:02 swildner Exp $
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
35 * SCSP subroutines
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>
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>
62 #include "scsp_msg.h"
63 #include "scsp_if.h"
64 #include "scsp_var.h"
67 * Hash an SCSP cache key
69 * Arguments:
70 * ckp pointer to an SCSP cache key structure
72 * Returns:
73 * hashed value
76 int
77 scsp_hash(Scsp_ckey *ckp)
79 int i, j, h;
82 * Turn cache key into a positive integer
84 h = 0;
85 for (i = ckp->key_len-1, j = 0;
86 i > 0 && j < sizeof(int);
87 i--, j++)
88 h = (h << 8) + ckp->key[i];
89 h = abs(h);
92 * Return the hashed value
94 return(h % SCSP_HASHSZ);
99 * Compare two SCSP IDs
101 * Arguments:
102 * id1p pointer to an SCSP ID structure
103 * id2p pointer to an SCSP ID structure
105 * Returns:
106 * < 0 id1 is less than id2
107 * 0 id1 and id2 are equal
108 * > 0 id1 is greater than id2
112 scsp_cmp_id(Scsp_id *id1p, Scsp_id *id2p)
114 int diff, i;
117 * Compare the two IDs, byte for byte
119 for (i = 0; i < id1p->id_len && i < id2p->id_len; i++) {
120 diff = id1p->id[i] - id2p->id[i];
121 if (diff) {
122 return(diff);
127 * IDs are equal. If lengths differ, the longer ID is
128 * greater than the shorter.
130 return(id1p->id_len - id2p->id_len);
135 * Compare two SCSP cache keys
137 * Arguments:
138 * ck1p pointer to an SCSP cache key structure
139 * ck2p pointer to an SCSP cache key structure
141 * Returns:
142 * < 0 ck1 is less than ck2
143 * 0 ck1 and ck2 are equal
144 * > 0 ck1 is greater than ck2
148 scsp_cmp_key(Scsp_ckey *ck1p, Scsp_ckey *ck2p)
150 int diff, i;
153 * Compare the two keys, byte for byte
155 for (i = 0; i < ck1p->key_len && i < ck2p->key_len; i++) {
156 diff = ck1p->key[i] - ck2p->key[i];
157 if (diff)
158 return(diff);
162 * Keys are equal. If lengths differ, the longer key is
163 * greater than the shorter.
165 return(ck1p->key_len - ck2p->key_len);
170 * Check whether the host system is an ATMARP server for
171 * the LIS associated with a given interface
173 * Arguments:
174 * netif pointer to the network interface name
176 * Returns:
177 * 1 host is a server
178 * 0 host is not a server
182 scsp_is_atmarp_server(char *netif)
184 int rc;
185 int buf_len = sizeof(struct air_asrv_rsp);
186 struct atminfreq air;
187 struct air_asrv_rsp *asrv_info;
190 * Get interface information from the kernel
192 strcpy(air.air_int_intf, netif);
193 air.air_opcode = AIOCS_INF_ASV;
194 buf_len = do_info_ioctl(&air, buf_len);
195 if (buf_len < 0)
196 return(0);
199 * Check the interface's ATMARP server address
201 asrv_info = (struct air_asrv_rsp *) air.air_buf_addr;
202 rc = (asrv_info->asp_addr.address_format == T_ATM_ABSENT) &&
203 (asrv_info->asp_subaddr.address_format ==
204 T_ATM_ABSENT);
205 UM_FREE(asrv_info);
206 return(rc);
211 * Make a copy of a cache summary entry
213 * Arguments:
214 * csep pointer to CSE entry to copy
216 * Returns:
217 * 0 copy failed
218 * else pointer to new CSE entry
221 Scsp_cse *
222 scsp_dup_cse(Scsp_cse *csep)
224 Scsp_cse *dupp;
227 * Allocate memory for the duplicate
229 dupp = (Scsp_cse *)UM_ALLOC(sizeof(Scsp_cse));
230 if (!dupp) {
231 scsp_mem_err("scsp_dup_cse: sizeof(Scsp_cse)");
235 * Copy data to the duplicate
237 UM_COPY(csep, dupp, sizeof(Scsp_cse));
238 dupp->sc_next = (Scsp_cse *)0;
240 return(dupp);
245 * Make a copy of a CSA or CSAS record
247 * Arguments:
248 * csap pointer to CSE entry to copy
250 * Returns:
251 * 0 copy failed
252 * else pointer to new CSA or CSAS record
255 Scsp_csa *
256 scsp_dup_csa(Scsp_csa *csap)
258 Scsp_csa *dupp;
259 Scsp_atmarp_csa *adp;
262 * Allocate memory for the duplicate
264 dupp = (Scsp_csa *)UM_ALLOC(sizeof(Scsp_csa));
265 if (!dupp) {
266 scsp_mem_err("scsp_dup_csa: sizeof(Scsp_csa)");
270 * Copy data to the duplicate
272 UM_COPY(csap, dupp, sizeof(Scsp_csa));
273 dupp->next = (Scsp_csa *)0;
276 * Copy protocol-specific data, if it's present
278 if (csap->atmarp_data) {
279 adp = (Scsp_atmarp_csa *)UM_ALLOC(sizeof(Scsp_atmarp_csa));
280 if (!adp) {
281 scsp_mem_err("scsp_dup_csa: sizeof(Scsp_atmarp_csa)");
283 UM_COPY(csap->atmarp_data, adp, sizeof(Scsp_atmarp_csa));
284 dupp->atmarp_data = adp;
287 return(dupp);
292 * Copy a cache summary entry into a CSAS
294 * Arguments:
295 * csep pointer to CSE entry to copy
297 * Returns:
298 * 0 copy failed
299 * else pointer to CSAS record summarizing the entry
302 Scsp_csa *
303 scsp_cse2csas(Scsp_cse *csep)
305 Scsp_csa *csap;
308 * Allocate memory for the duplicate
310 csap = (Scsp_csa *)UM_ALLOC(sizeof(Scsp_csa));
311 if (!csap) {
312 scsp_mem_err("scsp_cse2csas: sizeof(Scsp_csa)");
314 UM_ZERO(csap, sizeof(Scsp_csa));
317 * Copy data to the CSAS entry
319 csap->seq = csep->sc_seq;
320 csap->key = csep->sc_key;
321 csap->oid = csep->sc_oid;
323 return(csap);
328 * Copy an ATMARP cache entry into a cache summary entry
330 * Arguments:
331 * aap pointer to ATMARP cache entry to copy
333 * Returns:
334 * 0 copy failed
335 * else pointer to CSE record summarizing the entry
338 Scsp_cse *
339 scsp_atmarp2cse(Scsp_atmarp_msg *aap)
341 Scsp_cse *csep;
344 * Allocate memory for the duplicate
346 csep = (Scsp_cse *)UM_ALLOC(sizeof(Scsp_cse));
347 if (!csep) {
348 scsp_mem_err("scsp_atmarp2cse: sizeof(Scsp_cse)");
350 UM_ZERO(csep, sizeof(Scsp_cse));
353 * Copy data to the CSE entry
355 csep->sc_seq = aap->sa_seq;
356 csep->sc_key = aap->sa_key;
357 csep->sc_oid = aap->sa_oid;
359 return(csep);
364 * Clean up a DCS block. This routine is called to clear out any
365 * lingering state information when the CA FSM reverts to an 'earlier'
366 * state (Down or Master/Slave Negotiation).
368 * Arguments:
369 * dcsp pointer to a DCS control block for the neighbor
371 * Returns:
372 * none
375 void
376 scsp_dcs_cleanup(Scsp_dcs *dcsp)
378 Scsp_cse *csep, *ncsep;
379 Scsp_csa *csap, *next_csap;
380 Scsp_csu_rexmt *rxp, *rx_next;
383 * Free any CSAS entries waiting to be sent
385 for (csep = dcsp->sd_ca_csas; csep; csep = ncsep) {
386 ncsep = csep->sc_next;
387 UNLINK(csep, Scsp_cse, dcsp->sd_ca_csas, sc_next);
388 UM_FREE(csep);
392 * Free any entries on the CRL
394 for (csap = dcsp->sd_crl; csap; csap = next_csap) {
395 next_csap = csap->next;
396 UNLINK(csap, Scsp_csa, dcsp->sd_crl, next);
397 SCSP_FREE_CSA(csap);
401 * Free any saved CA message and cancel the CA
402 * retransmission timer
404 if (dcsp->sd_ca_rexmt_msg) {
405 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
406 dcsp->sd_ca_rexmt_msg = (Scsp_msg *)0;
408 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
411 * Free any saved CSU Solicit message and cancel the CSUS
412 * retransmission timer
414 if (dcsp->sd_csus_rexmt_msg) {
415 scsp_free_msg(dcsp->sd_csus_rexmt_msg);
416 dcsp->sd_csus_rexmt_msg = (Scsp_msg *)0;
418 HARP_CANCEL(&dcsp->sd_csus_rexmt_t);
421 * Free any entries on the CSU Request retransmission queue
423 for (rxp = dcsp->sd_csu_rexmt; rxp; rxp = rx_next) {
424 rx_next = rxp->sr_next;
425 HARP_CANCEL(&rxp->sr_t);
426 for (csap = rxp->sr_csa; csap; csap = next_csap) {
427 next_csap = csap->next;
428 SCSP_FREE_CSA(csap);
430 UNLINK(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt,
431 sr_next);
432 UM_FREE(rxp);
438 * Delete an SCSP DCS block and any associated information
440 * Arguments:
441 * dcsp pointer to a DCS control block to delete
443 * Returns:
444 * none
447 void
448 scsp_dcs_delete(Scsp_dcs *dcsp)
450 Scsp_cse *csep, *next_cse;
451 Scsp_csu_rexmt *rxp, *next_rxp;
452 Scsp_csa *csap, *next_csa;
455 * Cancel any pending DCS timers
457 HARP_CANCEL(&dcsp->sd_open_t);
458 HARP_CANCEL(&dcsp->sd_hello_h_t);
459 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
460 HARP_CANCEL(&dcsp->sd_ca_rexmt_t);
461 HARP_CANCEL(&dcsp->sd_csus_rexmt_t);
464 * Unlink the DCS block from the server block
466 UNLINK(dcsp, Scsp_dcs, dcsp->sd_server->ss_dcs, sd_next);
469 * Close the VCC to the DCS, if one is open
471 if (dcsp->sd_sock != -1) {
472 close(dcsp->sd_sock);
476 * Free any saved CA message
478 if (dcsp->sd_ca_rexmt_msg) {
479 scsp_free_msg(dcsp->sd_ca_rexmt_msg);
483 * Free any pending CSAs waiting for cache alignment
485 for (csep = dcsp->sd_ca_csas; csep; csep = next_cse) {
486 next_cse = csep->sc_next;
487 UM_FREE(csep);
491 * Free anything on the cache request list
493 for (csap = dcsp->sd_crl; csap; csap = next_csa) {
494 next_csa = csap->next;
495 SCSP_FREE_CSA(csap);
499 * Free any saved CSUS message
501 if (dcsp->sd_csus_rexmt_msg) {
502 scsp_free_msg(dcsp->sd_csus_rexmt_msg);
506 * Free anything on the CSU Request retransmit queue
508 for (rxp = dcsp->sd_csu_rexmt; rxp; rxp = next_rxp) {
510 * Cancel the retransmit timer
512 HARP_CANCEL(&rxp->sr_t);
515 * Free the CSAs to be retransmitted
517 for (csap = rxp->sr_csa; csap; csap = next_csa) {
518 next_csa = csap->next;
519 SCSP_FREE_CSA(csap);
523 * Free the CSU Req retransmission control block
525 next_rxp = rxp->sr_next;
526 UM_FREE(rxp);
530 * Free the DCS block
532 UM_FREE(dcsp);
537 * Shut down a server. This routine is called when a connection to
538 * a server is lost. It will clear the server's state without deleting
539 * the server.
541 * Arguments:
542 * ssp pointer to a server control block
544 * Returns:
545 * none
548 void
549 scsp_server_shutdown(Scsp_server *ssp)
551 int i;
552 Scsp_dcs *dcsp;
553 Scsp_cse *csep;
556 * Trace the shutdown
558 if (scsp_trace_mode & (SCSP_TRACE_IF_MSG | SCSP_TRACE_CFSM)) {
559 scsp_trace("Server %s being shut down\n",
560 ssp->ss_name);
564 * Terminate up all the DCS connections and clean
565 * up the control blocks
567 for (dcsp = ssp->ss_dcs; dcsp; dcsp = dcsp->sd_next) {
568 if (dcsp->sd_sock != -1) {
569 close(dcsp->sd_sock);
570 dcsp->sd_sock = -1;
572 HARP_CANCEL(&dcsp->sd_open_t);
573 HARP_CANCEL(&dcsp->sd_hello_h_t);
574 HARP_CANCEL(&dcsp->sd_hello_rcv_t);
575 scsp_dcs_cleanup(dcsp);
576 dcsp->sd_hello_state = SCSP_HFSM_DOWN;
577 dcsp->sd_ca_state = SCSP_CAFSM_DOWN;
578 dcsp->sd_client_state = SCSP_CIFSM_NULL;
582 * Clean up the server control block
584 if (ssp->ss_sock != -1) {
585 close(ssp->ss_sock);
586 ssp->ss_sock = -1;
588 if (ssp->ss_dcs_lsock != -1) {
589 close(ssp->ss_dcs_lsock);
590 ssp->ss_dcs_lsock = -1;
592 ssp->ss_state = SCSP_SS_NULL;
595 * Free the entries in the server's summary cache
597 for (i = 0; i < SCSP_HASHSZ; i++) {
598 while (ssp->ss_cache[i]) {
599 csep = ssp->ss_cache[i];
600 UNLINK(csep, Scsp_cse, ssp->ss_cache[i],
601 sc_next);
602 UM_FREE(csep);
609 * Delete an SCSP server block and any associated information
611 * Arguments:
612 * ssp pointer to a server control block to delete
614 * Returns:
615 * none
618 void
619 scsp_server_delete(Scsp_server *ssp)
621 int i;
622 Scsp_dcs *dcsp, *next_dcs;
623 Scsp_cse *csep, *next_cse;
626 * Unlink the server block from the chain
628 UNLINK(ssp, Scsp_server, scsp_server_head, ss_next);
631 * Free the DCS blocks associated with the server
633 for (dcsp = ssp->ss_dcs; dcsp; dcsp = next_dcs) {
634 next_dcs = dcsp->sd_next;
635 scsp_dcs_delete(dcsp);
639 * Free the entries in the server's summary cache
641 for (i = 0; i < SCSP_HASHSZ; i++) {
642 for (csep = ssp->ss_cache[i]; csep; csep = next_cse) {
643 next_cse = csep->sc_next;
644 UM_FREE(csep);
649 * Free the server block
651 UM_FREE(ssp->ss_name);
652 UM_FREE(ssp);
657 * Get informtion about a server from the kernel
659 * Arguments:
660 * ssp pointer to the server block
662 * Returns:
663 * 0 server info is OK
664 * errno server is not ready
668 scsp_get_server_info(Scsp_server *ssp)
670 int i, len, mtu, rc, sel;
671 struct atminfreq air;
672 struct air_netif_rsp *netif_rsp = (struct air_netif_rsp *)0;
673 struct air_int_rsp *intf_rsp = (struct air_int_rsp *)0;
674 struct air_cfg_rsp *cfg_rsp = (struct air_cfg_rsp *)0;
675 struct sockaddr_in *ip_addr;
676 Atm_addr_nsap *anp;
679 * Make sure we're the server for the interface
681 if (!scsp_is_atmarp_server(ssp->ss_intf)) {
682 rc = EINVAL;
683 goto server_info_done;
687 * Get the IP address and physical interface name
688 * associated with the network interface
690 UM_ZERO(&air, sizeof(struct atminfreq));
691 air.air_opcode = AIOCS_INF_NIF;
692 strcpy(air.air_netif_intf, ssp->ss_intf);
693 len = do_info_ioctl(&air, sizeof(struct air_netif_rsp));
694 if (len <= 0) {
695 rc = EIO;
696 goto server_info_done;
698 netif_rsp = (struct air_netif_rsp *)air.air_buf_addr;
700 ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr;
701 if (ip_addr->sin_family != AF_INET ||
702 ip_addr->sin_addr.s_addr == 0) {
703 rc = EADDRNOTAVAIL;
704 goto server_info_done;
708 * Get the MTU for the network interface
710 mtu = get_mtu(ssp->ss_intf);
711 if (mtu < 0) {
712 rc = EIO;
713 goto server_info_done;
717 * Get the ATM address associated with the
718 * physical interface
720 UM_ZERO(&air, sizeof(struct atminfreq));
721 air.air_opcode = AIOCS_INF_INT;
722 strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
723 len = do_info_ioctl(&air, sizeof(struct air_int_rsp));
724 if (len <= 0) {
725 rc = EIO;
726 goto server_info_done;
728 intf_rsp = (struct air_int_rsp *)air.air_buf_addr;
731 * Make sure we're running UNI signalling
733 if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 &&
734 intf_rsp->anp_sig_proto != ATM_SIG_UNI31 &&
735 intf_rsp->anp_sig_proto != ATM_SIG_UNI40) {
736 rc = EINVAL;
737 goto server_info_done;
741 * Check the physical interface's state
743 if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
744 rc = EHOSTDOWN;
745 goto server_info_done;
749 * Make sure the interface's address is valid
751 if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
752 !(intf_rsp->anp_addr.address_format ==
753 T_ATM_E164_ADDR &&
754 intf_rsp->anp_subaddr.address_format ==
755 T_ATM_ENDSYS_ADDR)) {
756 rc = EINVAL;
757 goto server_info_done;
761 * Find the selector byte value for the interface
763 for (i=0; i<strlen(ssp->ss_intf); i++) {
764 if (ssp->ss_intf[i] >= '0' &&
765 ssp->ss_intf[i] <= '9')
766 break;
768 sel = atoi(&ssp->ss_intf[i]);
771 * Get configuration information associated with the
772 * physical interface
774 UM_ZERO(&air, sizeof(struct atminfreq));
775 air.air_opcode = AIOCS_INF_CFG;
776 strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
777 len = do_info_ioctl(&air, sizeof(struct air_cfg_rsp));
778 if (len <= 0) {
779 rc = EIO;
780 goto server_info_done;
782 cfg_rsp = (struct air_cfg_rsp *)air.air_buf_addr;
785 * Update the server entry
787 UM_COPY(&ip_addr->sin_addr, ssp->ss_lsid.id, ssp->ss_id_len);
788 ssp->ss_lsid.id_len = ssp->ss_id_len;
789 ssp->ss_mtu = mtu + 8;
790 ATM_ADDR_COPY(&intf_rsp->anp_addr, &ssp->ss_addr);
791 ATM_ADDR_COPY(&intf_rsp->anp_subaddr, &ssp->ss_subaddr);
792 if (ssp->ss_addr.address_format == T_ATM_ENDSYS_ADDR) {
793 anp = (Atm_addr_nsap *)ssp->ss_addr.address;
794 anp->aan_sel = sel;
795 } else if (ssp->ss_addr.address_format == T_ATM_E164_ADDR &&
796 ssp->ss_subaddr.address_format ==
797 T_ATM_ENDSYS_ADDR) {
798 anp = (Atm_addr_nsap *)ssp->ss_subaddr.address;
799 anp->aan_sel = sel;
801 ssp->ss_media = cfg_rsp->acp_cfg.ac_media;
802 rc = 0;
805 * Free dynamic data
807 server_info_done:
808 if (netif_rsp)
809 UM_FREE(netif_rsp);
810 if (intf_rsp)
811 UM_FREE(intf_rsp);
812 if (cfg_rsp)
813 UM_FREE(cfg_rsp);
815 return(rc);
820 * Process a CA message
822 * Arguments:
823 * dcsp pointer to a DCS control block for the neighbor
824 * cap pointer to the CA part of the received message
826 * Returns:
827 * none
830 void
831 scsp_process_ca(Scsp_dcs* dcsp, Scsp_ca *cap)
833 Scsp_csa *csap, *next_csap;
834 Scsp_cse *csep;
835 Scsp_server *ssp = dcsp->sd_server;
838 * Process CSAS records from the CA message
840 for (csap = cap->ca_csa_rec; csap; csap = next_csap) {
841 next_csap = csap->next;
842 SCSP_LOOKUP(ssp, &csap->key, csep);
843 if (!csep || (scsp_cmp_id(&csap->oid,
844 &csep->sc_oid) == 0 &&
845 csap->seq > csep->sc_seq)) {
847 * CSAS entry not in cache or more
848 * up to date than cache, add it to CRL
850 UNLINK(csap, Scsp_csa, cap->ca_csa_rec, next);
851 LINK2TAIL(csap, Scsp_csa, dcsp->sd_crl, next);
858 * Process a Cache Response message from a server
860 * Arguments:
861 * ssp pointer to the server block
862 * smp pointer to the message
864 * Returns:
865 * none
868 void
869 scsp_process_cache_rsp(Scsp_server *ssp, Scsp_if_msg *smp)
871 int len;
872 Scsp_atmarp_msg *aap;
873 Scsp_cse *csep;
876 * Loop through the message, processing each cache entry
878 len = smp->si_len;
879 len -= sizeof(Scsp_if_msg_hdr);
880 aap = &smp->si_atmarp;
881 while (len > 0) {
882 switch(smp->si_proto) {
883 case SCSP_ATMARP_PROTO:
885 * If we already have an entry with this key,
886 * delete it
888 SCSP_LOOKUP(ssp, &aap->sa_key, csep);
889 if (csep) {
890 SCSP_DELETE(ssp, csep);
891 UM_FREE(csep);
895 * Copy the data from the server to a cache
896 * summary entry
898 csep = scsp_atmarp2cse(aap);
901 * Point past this entry
903 len -= sizeof(Scsp_atmarp_msg);
904 aap++;
905 break;
906 case SCSP_NHRP_PROTO:
907 default:
909 * Not implemented yet
911 return;
915 * Add the new summary entry to the cache
917 SCSP_ADD(ssp, csep);
923 * Propagate a CSA to all the DCSs in the server group except
924 * the one the CSA was received from
926 * Arguments:
927 * dcsp pointer to a the DCS the CSA came from
928 * csap pointer to a the CSA
930 * Returns:
931 * 0 success
932 * errno error encountered
936 scsp_propagate_csa(Scsp_dcs *dcsp, Scsp_csa *csap)
938 int rc, ret_rc = 0;
939 Scsp_server *ssp = dcsp->sd_server;
940 Scsp_dcs *dcsp1;
941 Scsp_csa *csap1;
944 * Check the hop count in the CSA
946 if (csap->hops <= 1)
947 return(0);
950 * Pass the cache entry on to the server's other DCSs
952 for (dcsp1 = ssp->ss_dcs; dcsp1; dcsp1 = dcsp1->sd_next) {
954 * Skip this DCS if it's the one we got
955 * the entry from
957 if (dcsp1 == dcsp)
958 continue;
961 * Copy the CSA
963 csap1 = scsp_dup_csa(csap);
966 * Decrement the hop count
968 csap1->hops--;
971 * Send the copy of the CSA to the CA FSM for the DCS
973 rc = scsp_cafsm(dcsp1, SCSP_CAFSM_CACHE_UPD,
974 (void *) csap1);
975 if (rc)
976 ret_rc = rc;
979 return(ret_rc);
984 * Update SCSP's cache given a CSA or CSAS
986 * Arguments:
987 * dcsp pointer to a DCS
988 * csap pointer to a CSA
990 * Returns:
991 * none
994 void
995 scsp_update_cache(Scsp_dcs *dcsp, Scsp_csa *csap)
997 Scsp_cse *csep;
1000 * Check whether we already have this in the cache
1002 SCSP_LOOKUP(dcsp->sd_server, &csap->key, csep);
1005 * If we don't already have it and it's not being deleted,
1006 * build a new cache summary entry
1008 if (!csep && !csap->null) {
1010 * Get memory for a new entry
1012 csep = (Scsp_cse *)UM_ALLOC(sizeof(Scsp_cse));
1013 if (!csep) {
1014 scsp_mem_err("scsp_update_cache: sizeof(Scsp_cse)");
1016 UM_ZERO(csep, sizeof(Scsp_cse));
1019 * Fill out the new cache summary entry
1021 csep->sc_seq = csap->seq;
1022 csep->sc_key = csap->key;
1023 csep->sc_oid = csap->oid;
1026 * Add the new entry to the cache
1028 SCSP_ADD(dcsp->sd_server, csep);
1032 * Update or delete the entry
1034 if (csap->null) {
1036 * The null flag is set--delete the entry
1038 if (csep) {
1039 SCSP_DELETE(dcsp->sd_server, csep);
1040 UM_FREE(csep);
1042 } else {
1044 * Update the existing entry
1046 csep->sc_seq = csap->seq;
1047 csep->sc_oid = csap->oid;
1053 * Reconfigure SCSP
1055 * Called as the result of a SIGHUP interrupt. Reread the
1056 * configuration file and solicit the cache from the server.
1058 * Arguments:
1059 * none
1061 * Returns:
1062 * none
1065 void
1066 scsp_reconfigure(void)
1068 int rc;
1069 Scsp_server *ssp;
1072 * Log a message saying we're reconfiguring
1074 scsp_log(LOG_ERR, "Reconfiguring ...");
1077 * Re-read the configuration file
1079 rc = scsp_config(scsp_config_file);
1080 if (rc) {
1081 scsp_log(LOG_ERR, "Found %d error%s in configuration file",
1082 rc, ((rc == 1) ? "" : "s"));
1083 exit(1);
1087 * If a connection to a server is open, get the cache from
1088 * the server
1090 for (ssp = scsp_server_head; ssp; ssp = ssp->ss_next) {
1091 if (ssp->ss_sock != -1) {
1092 rc = scsp_send_cache_ind(ssp);