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/atmarpd/atmarp_scsp.c,v 1.3 1999/08/28 01:15:30 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/atmarpd/atmarp_scsp.c,v 1.2 2003/06/17 04:29:52 dillon Exp $
31 * Server Cache Synchronization Protocol (SCSP) Support
32 * ----------------------------------------------------
34 * SCSP-ATMARP server interface: SCSP/ATMARP interface code
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netatm/port.h>
44 #include <netatm/queue.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_if.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_sys.h>
49 #include <netatm/atm_ioctl.h>
50 #include <netatm/uni/uniip_var.h>
61 #include "../scspd/scsp_msg.h"
62 #include "../scspd/scsp_if.h"
63 #include "../scspd/scsp_var.h"
64 #include "atmarp_var.h"
67 * Send the cache for a LIS to SCSP
71 * aip pointer to interface block
74 * 0 cache sent to SCSP OK
75 * errno reason for failure
79 atmarp_scsp_cache(aip, msg)
85 Scsp_if_msg *smp = (Scsp_if_msg *)0;
89 * Figure out how big the message needs to be
91 len = sizeof(Scsp_if_msg_hdr);
92 for (i = 0; i < ATMARP_HASHSIZ; i++) {
93 for (aap = aip->ai_arptbl[i]; aap; aap = aap->aa_next) {
94 len += sizeof(Scsp_atmarp_msg);
99 * Get memory for the cache message
101 smp = (Scsp_if_msg *)UM_ALLOC(len);
103 atmarp_mem_err("atmarp_scsp_cache: len");
108 * Set header fields in SCSP message
110 smp->si_type = SCSP_CACHE_RSP;
111 smp->si_proto = SCSP_PROTO_ATMARP;
113 smp->si_tok = msg->si_tok;
116 * Loop through the cache, adding each entry to the SCSP
117 * Cache Response message
119 sap = &smp->si_atmarp;
120 for (i = 0; i < ATMARP_HASHSIZ; i++) {
121 for (aap = aip->ai_arptbl[i]; aap; aap = aap->aa_next) {
122 sap->sa_state = SCSP_ASTATE_NEW;
123 sap->sa_cpa = aap->aa_dstip;
124 ATM_ADDR_COPY(&aap->aa_dstatm, &sap->sa_cha);
125 ATM_ADDR_COPY(&aap->aa_dstatmsub, &sap->sa_csa);
126 sap->sa_key = aap->aa_key;
127 sap->sa_oid = aap->aa_oid;
128 sap->sa_seq = aap->aa_seq;
134 * Send the message to SCSP
136 rc = atmarp_scsp_out(aip, (char *)smp, len);
149 * Answer a reqeust for information about a cache entry
152 * aap pointer to entry
153 * state entry's new state
157 * errno reason for failure
161 atmarp_scsp_solicit(aip, smp)
167 Scsp_if_msg *rsp = (Scsp_if_msg *)0;
170 * Search the interface's ATMARP cache for an entry with
171 * the specified cache key and origin ID
173 for (i = 0; i < ATMARP_HASHSIZ; i++) {
174 for (aap = aip->ai_arptbl[i]; aap; aap = aap->aa_next) {
175 if (KEY_EQUAL(&aap->aa_key,
176 &smp->si_sum.ss_key) &&
177 OID_EQUAL(&aap->aa_oid,
178 &smp->si_sum.ss_oid))
186 * Get storage for a Solicit Response
188 rsp = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
190 atmarp_mem_err("atmarp_scsp_solicit: sizeof(Scsp_if_msg)");
192 UM_ZERO(rsp, sizeof(Scsp_if_msg));
195 * Fill out the Solicit Rsp
197 rsp->si_type = SCSP_SOLICIT_RSP;
198 rsp->si_proto = smp->si_proto;
199 rsp->si_tok = smp->si_tok;
203 * Copy fields from the ATMARP entry to the SCSP
204 * Update Request message
206 rsp->si_rc = SCSP_RSP_OK;
207 rsp->si_len = sizeof(Scsp_if_msg_hdr) +
208 sizeof(Scsp_atmarp_msg);
209 rsp->si_atmarp.sa_state = SCSP_ASTATE_UPD;
210 rsp->si_atmarp.sa_cpa = aap->aa_dstip;
211 ATM_ADDR_COPY(&aap->aa_dstatm, &rsp->si_atmarp.sa_cha);
212 ATM_ADDR_COPY(&aap->aa_dstatmsub, &rsp->si_atmarp.sa_csa);
213 rsp->si_atmarp.sa_key = aap->aa_key;
214 rsp->si_atmarp.sa_oid = aap->aa_oid;
215 rsp->si_atmarp.sa_seq = aap->aa_seq;
218 * Entry not found--set return code
220 rsp->si_rc = SCSP_RSP_NOT_FOUND;
221 rsp->si_len = smp->si_len;
222 rsp->si_sum = smp->si_sum;
226 * Send the message to SCSP
228 rc = atmarp_scsp_out(aip, (char *)rsp, rsp->si_len);
236 * Send a cache update to SCSP
239 * aap pointer to entry
240 * state entry's new state
244 * errno reason for failure
248 atmarp_scsp_update(aap, state)
253 Atmarp_intf *aip = aap->aa_intf;
254 Scsp_if_msg *smp = (Scsp_if_msg *)0;
257 * Make sure the connection to SCSP is active
259 if (aip->ai_state == AI_STATE_NULL) {
264 * Get memory for the cache message
266 smp = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
268 atmarp_mem_err("atmarp_scsp_update: sizeof(Scsp_if_msg)");
270 UM_ZERO(smp, sizeof(Scsp_if_msg));
273 * Set header fields in SCSP message
275 smp->si_type = SCSP_UPDATE_REQ;
276 smp->si_proto = SCSP_PROTO_ATMARP;
277 smp->si_len = sizeof(Scsp_if_msg_hdr) + sizeof(Scsp_atmarp_msg);
280 * Copy fields from the ATMARP entry to the SCSP
281 * Update Request message
283 smp->si_atmarp.sa_state = state;
284 smp->si_atmarp.sa_cpa = aap->aa_dstip;
285 ATM_ADDR_COPY(&aap->aa_dstatm, &smp->si_atmarp.sa_cha);
286 ATM_ADDR_COPY(&aap->aa_dstatmsub, &smp->si_atmarp.sa_csa);
287 smp->si_atmarp.sa_key = aap->aa_key;
288 smp->si_atmarp.sa_oid = aap->aa_oid;
289 smp->si_atmarp.sa_seq = aap->aa_seq;
292 * Send the message to SCSP
294 rc = atmarp_scsp_out(aap->aa_intf, (char *)smp, smp->si_len);
302 * Respond to a Cache Update Indication from SCSP
306 * aip pointer to interface control block
307 * smp pointer to message from SCSP
310 * 0 Message processed OK
311 * errno Reason for failure
315 atmarp_scsp_update_in(aip, smp)
325 ATMARP_LOOKUP(aip, smp->si_atmarp.sa_cpa.s_addr, aap);
328 * Whether we accept the request depends on whether we
329 * already have an entry for it
333 * We don't have this entry--accept it
338 * We do have an entry for this host--check the
341 if (bcmp(&aip->ai_ip_addr.s_addr,
342 smp->si_atmarp.sa_oid.id,
343 SCSP_ATMARP_ID_LEN) == 0) {
345 * The received entry originated with us--
349 } else if (bcmp(&aip->ai_ip_addr.s_addr,
351 SCSP_ATMARP_ID_LEN) == 0) {
353 * We originated the entry we currently have--
354 * only accept the new one if SCSP has higher
355 * priority than the existing entry
357 accept = aap->aa_origin < UAO_SCSP;
360 * Accept the entry if it is more up-to-date
361 * than the existing entry
363 accept = KEY_EQUAL(&aap->aa_key,
364 &smp->si_atmarp.sa_key) &&
365 OID_EQUAL(&aap->aa_oid,
366 &smp->si_atmarp.sa_oid) &&
367 (aap->aa_seq < smp->si_atmarp.sa_seq);
372 * Add the entry to the cache, if appropriate
377 * Copy info from SCSP to a new cache entry
379 aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
381 atmarp_mem_err("atmarp_scsp_update_in: sizeof(Atmarp)");
382 UM_ZERO(aap, sizeof(Atmarp));
384 aap->aa_dstip = smp->si_atmarp.sa_cpa;
385 aap->aa_dstatm = smp->si_atmarp.sa_cha;
386 aap->aa_dstatmsub = smp->si_atmarp.sa_csa;
387 aap->aa_key = smp->si_atmarp.sa_key;
388 aap->aa_oid = smp->si_atmarp.sa_oid;
389 aap->aa_seq = smp->si_atmarp.sa_seq;
391 aap->aa_origin = UAO_SCSP;
394 * Add the new entry to our cache
396 ATMARP_ADD(aip, aap);
399 * Update the existing entry
401 aap->aa_dstip = smp->si_atmarp.sa_cpa;
402 aap->aa_dstatm = smp->si_atmarp.sa_cha;
403 aap->aa_dstatmsub = smp->si_atmarp.sa_csa;
404 aap->aa_key = smp->si_atmarp.sa_key;
405 aap->aa_oid = smp->si_atmarp.sa_oid;
406 aap->aa_seq = smp->si_atmarp.sa_seq;
407 aap->aa_origin = UAO_SCSP;
411 * Send the updated entry to the kernel
413 if (atmarp_update_kernel(aap) == 0)
422 * Turn the received message into a response
424 smp->si_type = SCSP_UPDATE_RSP;
428 * Send the message to SCSP
430 rc = atmarp_scsp_out(aip, (char *)smp, smp->si_len);
437 * Read and process a message from SCSP
441 * aip interface for read
445 * errno reason for failure
449 atmarp_scsp_read(aip)
453 char *buff = (char *)0;
455 Scsp_if_msg_hdr msg_hdr;
458 * Read the header of the message from SCSP
460 len = read(aip->ai_scsp_sock, (char *)&msg_hdr,
465 } else if (len != sizeof(msg_hdr)) {
471 * Get a buffer that will hold the message
473 buff = UM_ALLOC(msg_hdr.sh_len);
475 atmarp_mem_err("atmarp_scsp_read: msg_hdr.sh_len");
476 UM_COPY(&msg_hdr, buff, sizeof(msg_hdr));
479 * Read the rest of the message, if there is more than
482 len = msg_hdr.sh_len - sizeof(msg_hdr);
484 len = read(aip->ai_scsp_sock, buff + sizeof(msg_hdr),
489 } else if (len != msg_hdr.sh_len - sizeof(msg_hdr)) {
496 * Handle the message based on its type
498 smp = (Scsp_if_msg *)buff;
499 switch(smp->si_type) {
501 if (smp->si_rc != SCSP_RSP_OK) {
507 rc = atmarp_scsp_cache(aip, smp);
509 case SCSP_SOLICIT_IND:
510 rc = atmarp_scsp_solicit(aip, smp);
512 case SCSP_UPDATE_IND:
513 rc = atmarp_scsp_update_in(aip, smp);
515 case SCSP_UPDATE_RSP:
517 * Ignore Update Responses
521 atmarp_log(LOG_ERR, "Unexpected SCSP message received");
534 * Error on socket to SCSP--close the socket and set the state
535 * so that we know to retry when the cache timer fires.
537 atmarp_scsp_close(aip);
544 * Send a message to SCSP
548 * aip pointer to ATMARP interface to send message on
549 * buff pointer to message buffer
550 * len length of message
554 * errno reason for failure
558 atmarp_scsp_out(aip, buff, len)
566 * Send the message to SCSP
568 rc = write(aip->ai_scsp_sock, buff, len);
573 * Error on write--close the socket to SCSP, clean up and
574 * set the state so that we know to retry when the cache
577 atmarp_scsp_close(aip);
580 * Set the return code
593 * Set up a socket and connect to SCSP
596 * aip pointer to interface block
599 * 0 success, ai_scsp_sock is set
600 * errno reason for failure
605 atmarp_scsp_connect(aip)
612 static struct sockaddr local_addr = {
613 #if (defined(BSD) && (BSD >= 199103))
614 sizeof(struct sockaddr), /* sa_len */
616 AF_UNIX, /* sa_family */
617 ATMARP_SOCK_PREFIX /* sa_data */
619 static struct sockaddr scsp_addr = {
620 #if (defined(BSD) && (BSD >= 199103))
621 sizeof(struct sockaddr), /* sa_len */
623 AF_UNIX, /* sa_family */
624 SCSPD_SOCK_NAME /* sa_data */
628 * Construct a name for the socket
630 strncpy(local_addr.sa_data, ATMARP_SOCK_PREFIX,
631 sizeof(local_addr.sa_data));
632 (void)strncat(local_addr.sa_data, aip->ai_intf,
633 sizeof(local_addr.sa_data));
634 sn = strdup(local_addr.sa_data);
636 atmarp_mem_err("atmarp_scsp_connect: strdup");
639 * Clean up any old socket
642 if (rc < 0 && errno != ENOENT)
646 * Open a socket to SCSP
648 sd = socket(PF_UNIX, SOCK_STREAM, 0);
653 if (sd > atmarp_max_socket) {
654 atmarp_max_socket = sd;
658 * Set non-blocking I/O
661 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
663 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
667 goto scsp_connect_fail;
671 * Bind the local socket address
673 rc = bind(sd, &local_addr, sizeof(local_addr));
676 goto scsp_connect_fail;
682 rc = connect(sd, &scsp_addr, sizeof(scsp_addr));
685 goto scsp_connect_fail;
689 * Save socket information in interface control block
691 aip->ai_scsp_sock = sd;
692 aip->ai_scsp_sockname = sn;
693 aip->ai_state = AI_STATE_UP;
696 * Send configuration information to SCSP
698 UM_ZERO(&cfg_msg, sizeof(cfg_msg));
699 cfg_msg.si_type = SCSP_CFG_REQ;
700 cfg_msg.si_proto = SCSP_PROTO_ATMARP;
701 strcpy(cfg_msg.si_cfg.atmarp_netif, aip->ai_intf);
702 len =sizeof(Scsp_if_msg_hdr) + strlen(aip->ai_intf) + 1;
703 cfg_msg.si_len = len;
704 rc = atmarp_scsp_out(aip, (char *)&cfg_msg, len);
713 aip->ai_scsp_sock = -1;
715 aip->ai_scsp_sockname = NULL;
716 aip->ai_state = AI_STATE_NULL;
722 * Close a socket connection to SCSP
725 * aip pointer to interface block for connection to be closed
733 atmarp_scsp_close(aip)
737 * Close and unlink the SCSP socket
739 (void)close(aip->ai_scsp_sock);
740 aip->ai_scsp_sock = -1;
741 (void)unlink(aip->ai_scsp_sockname);
742 UM_FREE(aip->ai_scsp_sockname);
743 aip->ai_scsp_sockname = NULL;
745 aip->ai_state = AI_STATE_NULL;
752 * Disconnect an interface from SCSP
755 * aip pointer to interface block for connection to be closed
758 * 0 success, ai_scsp_sock is set
759 * errno reason for failure
764 atmarp_scsp_disconnect(aip)
771 * Close and unlink the SCSP socket
773 atmarp_scsp_close(aip);
776 * Free the ATMARP cache associated with the interface
778 for (i = 0; i < ATMARP_HASHSIZ; i++) {
779 for (aap = aip->ai_arptbl[i]; aap; aap = aap->aa_next) {
782 aip->ai_arptbl[i] = (Atmarp *)0;