vn.4: Describe autocloning & use standard description for kernel modules
[dragonfly.git] / usr.sbin / atm / atmarpd / atmarp_scsp.c
blob371e7832dd3879e03011d5622aea2be1dd1a0adf
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/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.4 2004/12/18 22:48:02 swildner 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>
41 #include <net/if.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>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <libatm.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <syslog.h>
59 #include <unistd.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
70 * Arguments:
71 * aip pointer to interface block
73 * Returns:
74 * 0 cache sent to SCSP OK
75 * errno reason for failure
78 int
79 atmarp_scsp_cache(Atmarp_intf *aip, Scsp_if_msg *msg)
81 int i, len, rc = 0;
82 Atmarp *aap;
83 Scsp_if_msg *smp = NULL;
84 Scsp_atmarp_msg *sap;
87 * Figure out how big the message needs to be
89 len = sizeof(Scsp_if_msg_hdr);
90 for (i = 0; i < ATMARP_HASHSIZ; i++) {
91 for (aap = aip->ai_arptbl[i]; aap; aap = aap->aa_next) {
92 len += sizeof(Scsp_atmarp_msg);
97 * Get memory for the cache message
99 smp = (Scsp_if_msg *)UM_ALLOC(len);
100 if (!smp) {
101 atmarp_mem_err("atmarp_scsp_cache: len");
103 UM_ZERO(smp, len);
106 * Set header fields in SCSP message
108 smp->si_type = SCSP_CACHE_RSP;
109 smp->si_proto = SCSP_PROTO_ATMARP;
110 smp->si_len = len;
111 smp->si_tok = msg->si_tok;
114 * Loop through the cache, adding each entry to the SCSP
115 * Cache Response message
117 sap = &smp->si_atmarp;
118 for (i = 0; i < ATMARP_HASHSIZ; i++) {
119 for (aap = aip->ai_arptbl[i]; aap; aap = aap->aa_next) {
120 sap->sa_state = SCSP_ASTATE_NEW;
121 sap->sa_cpa = aap->aa_dstip;
122 ATM_ADDR_COPY(&aap->aa_dstatm, &sap->sa_cha);
123 ATM_ADDR_COPY(&aap->aa_dstatmsub, &sap->sa_csa);
124 sap->sa_key = aap->aa_key;
125 sap->sa_oid = aap->aa_oid;
126 sap->sa_seq = aap->aa_seq;
127 sap++;
132 * Send the message to SCSP
134 rc = atmarp_scsp_out(aip, (char *)smp, len);
137 * Free the message
139 if (smp)
140 UM_FREE(smp);
142 return(rc);
147 * Answer a reqeust for information about a cache entry
149 * Arguments:
150 * aap pointer to entry
151 * state entry's new state
153 * Returns:
154 * 0 success
155 * errno reason for failure
159 atmarp_scsp_solicit(Atmarp_intf *aip, Scsp_if_msg *smp)
161 int i, rc = 0;
162 Atmarp *aap;
163 Scsp_if_msg *rsp = NULL;
166 * Search the interface's ATMARP cache for an entry with
167 * the specified cache key and origin ID
169 for (i = 0; i < ATMARP_HASHSIZ; i++) {
170 for (aap = aip->ai_arptbl[i]; aap; aap = aap->aa_next) {
171 if (KEY_EQUAL(&aap->aa_key,
172 &smp->si_sum.ss_key) &&
173 OID_EQUAL(&aap->aa_oid,
174 &smp->si_sum.ss_oid))
175 break;
177 if (aap)
178 break;
182 * Get storage for a Solicit Response
184 rsp = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
185 if (!rsp) {
186 atmarp_mem_err("atmarp_scsp_solicit: sizeof(Scsp_if_msg)");
188 UM_ZERO(rsp, sizeof(Scsp_if_msg));
191 * Fill out the Solicit Rsp
193 rsp->si_type = SCSP_SOLICIT_RSP;
194 rsp->si_proto = smp->si_proto;
195 rsp->si_tok = smp->si_tok;
197 if (aap) {
199 * Copy fields from the ATMARP entry to the SCSP
200 * Update Request message
202 rsp->si_rc = SCSP_RSP_OK;
203 rsp->si_len = sizeof(Scsp_if_msg_hdr) +
204 sizeof(Scsp_atmarp_msg);
205 rsp->si_atmarp.sa_state = SCSP_ASTATE_UPD;
206 rsp->si_atmarp.sa_cpa = aap->aa_dstip;
207 ATM_ADDR_COPY(&aap->aa_dstatm, &rsp->si_atmarp.sa_cha);
208 ATM_ADDR_COPY(&aap->aa_dstatmsub, &rsp->si_atmarp.sa_csa);
209 rsp->si_atmarp.sa_key = aap->aa_key;
210 rsp->si_atmarp.sa_oid = aap->aa_oid;
211 rsp->si_atmarp.sa_seq = aap->aa_seq;
212 } else {
214 * Entry not found--set return code
216 rsp->si_rc = SCSP_RSP_NOT_FOUND;
217 rsp->si_len = smp->si_len;
218 rsp->si_sum = smp->si_sum;
222 * Send the message to SCSP
224 rc = atmarp_scsp_out(aip, (char *)rsp, rsp->si_len);
225 UM_FREE(rsp);
227 return(rc);
232 * Send a cache update to SCSP
234 * Arguments:
235 * aap pointer to entry
236 * state entry's new state
238 * Returns:
239 * 0 success
240 * errno reason for failure
244 atmarp_scsp_update(Atmarp *aap, int state)
246 int rc = 0;
247 Atmarp_intf *aip = aap->aa_intf;
248 Scsp_if_msg *smp = NULL;
251 * Make sure the connection to SCSP is active
253 if (aip->ai_state == AI_STATE_NULL) {
254 return(0);
258 * Get memory for the cache message
260 smp = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
261 if (!smp) {
262 atmarp_mem_err("atmarp_scsp_update: sizeof(Scsp_if_msg)");
264 UM_ZERO(smp, sizeof(Scsp_if_msg));
267 * Set header fields in SCSP message
269 smp->si_type = SCSP_UPDATE_REQ;
270 smp->si_proto = SCSP_PROTO_ATMARP;
271 smp->si_len = sizeof(Scsp_if_msg_hdr) + sizeof(Scsp_atmarp_msg);
274 * Copy fields from the ATMARP entry to the SCSP
275 * Update Request message
277 smp->si_atmarp.sa_state = state;
278 smp->si_atmarp.sa_cpa = aap->aa_dstip;
279 ATM_ADDR_COPY(&aap->aa_dstatm, &smp->si_atmarp.sa_cha);
280 ATM_ADDR_COPY(&aap->aa_dstatmsub, &smp->si_atmarp.sa_csa);
281 smp->si_atmarp.sa_key = aap->aa_key;
282 smp->si_atmarp.sa_oid = aap->aa_oid;
283 smp->si_atmarp.sa_seq = aap->aa_seq;
286 * Send the message to SCSP
288 rc = atmarp_scsp_out(aap->aa_intf, (char *)smp, smp->si_len);
290 UM_FREE(smp);
291 return(rc);
296 * Respond to a Cache Update Indication from SCSP
299 * Arguments:
300 * aip pointer to interface control block
301 * smp pointer to message from SCSP
303 * Returns:
304 * 0 Message processed OK
305 * errno Reason for failure
309 atmarp_scsp_update_in(Atmarp_intf *aip, Scsp_if_msg *smp)
311 int accept, rc;
312 Atmarp *aap;
315 * Look up the entry
317 ATMARP_LOOKUP(aip, smp->si_atmarp.sa_cpa.s_addr, aap);
320 * Whether we accept the request depends on whether we
321 * already have an entry for it
323 if (!aap) {
325 * We don't have this entry--accept it
327 accept = 1;
328 } else {
330 * We do have an entry for this host--check the
331 * origin ID
333 if (bcmp(&aip->ai_ip_addr.s_addr,
334 smp->si_atmarp.sa_oid.id,
335 SCSP_ATMARP_ID_LEN) == 0) {
337 * The received entry originated with us--
338 * reject it
340 accept = 0;
341 } else if (bcmp(&aip->ai_ip_addr.s_addr,
342 aap->aa_oid.id,
343 SCSP_ATMARP_ID_LEN) == 0) {
345 * We originated the entry we currently have--
346 * only accept the new one if SCSP has higher
347 * priority than the existing entry
349 accept = aap->aa_origin < UAO_SCSP;
350 } else {
352 * Accept the entry if it is more up-to-date
353 * than the existing entry
355 accept = KEY_EQUAL(&aap->aa_key,
356 &smp->si_atmarp.sa_key) &&
357 OID_EQUAL(&aap->aa_oid,
358 &smp->si_atmarp.sa_oid) &&
359 (aap->aa_seq < smp->si_atmarp.sa_seq);
364 * Add the entry to the cache, if appropriate
366 if (accept) {
367 if (!aap) {
369 * Copy info from SCSP to a new cache entry
371 aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
372 if (!aap)
373 atmarp_mem_err("atmarp_scsp_update_in: sizeof(Atmarp)");
374 UM_ZERO(aap, sizeof(Atmarp));
376 aap->aa_dstip = smp->si_atmarp.sa_cpa;
377 aap->aa_dstatm = smp->si_atmarp.sa_cha;
378 aap->aa_dstatmsub = smp->si_atmarp.sa_csa;
379 aap->aa_key = smp->si_atmarp.sa_key;
380 aap->aa_oid = smp->si_atmarp.sa_oid;
381 aap->aa_seq = smp->si_atmarp.sa_seq;
382 aap->aa_intf = aip;
383 aap->aa_origin = UAO_SCSP;
386 * Add the new entry to our cache
388 ATMARP_ADD(aip, aap);
389 } else {
391 * Update the existing entry
393 aap->aa_dstip = smp->si_atmarp.sa_cpa;
394 aap->aa_dstatm = smp->si_atmarp.sa_cha;
395 aap->aa_dstatmsub = smp->si_atmarp.sa_csa;
396 aap->aa_key = smp->si_atmarp.sa_key;
397 aap->aa_oid = smp->si_atmarp.sa_oid;
398 aap->aa_seq = smp->si_atmarp.sa_seq;
399 aap->aa_origin = UAO_SCSP;
403 * Send the updated entry to the kernel
405 if (atmarp_update_kernel(aap) == 0)
406 rc = SCSP_RSP_OK;
407 else
408 rc = SCSP_RSP_REJ;
409 } else {
410 rc = SCSP_RSP_REJ;
414 * Turn the received message into a response
416 smp->si_type = SCSP_UPDATE_RSP;
417 smp->si_rc = rc;
420 * Send the message to SCSP
422 rc = atmarp_scsp_out(aip, (char *)smp, smp->si_len);
424 return(rc);
429 * Read and process a message from SCSP
432 * Arguments:
433 * aip interface for read
435 * Returns:
436 * 0 success
437 * errno reason for failure
441 atmarp_scsp_read(Atmarp_intf *aip)
443 int len, rc = 0;
444 char *buff = NULL;
445 Scsp_if_msg *smp;
446 Scsp_if_msg_hdr msg_hdr;
449 * Read the header of the message from SCSP
451 len = read(aip->ai_scsp_sock, (char *)&msg_hdr,
452 sizeof(msg_hdr));
453 if (len == -1) {
454 rc = errno;
455 goto read_fail;
456 } else if (len != sizeof(msg_hdr)) {
457 rc = EMSGSIZE;
458 goto read_fail;
462 * Get a buffer that will hold the message
464 buff = UM_ALLOC(msg_hdr.sh_len);
465 if (!buff)
466 atmarp_mem_err("atmarp_scsp_read: msg_hdr.sh_len");
467 UM_COPY(&msg_hdr, buff, sizeof(msg_hdr));
470 * Read the rest of the message, if there is more than
471 * just a header
473 len = msg_hdr.sh_len - sizeof(msg_hdr);
474 if (len > 0) {
475 len = read(aip->ai_scsp_sock, buff + sizeof(msg_hdr),
476 len);
477 if (len == -1) {
478 rc = errno;
479 goto read_fail;
480 } else if (len != msg_hdr.sh_len - sizeof(msg_hdr)) {
481 rc = EMSGSIZE;
482 goto read_fail;
487 * Handle the message based on its type
489 smp = (Scsp_if_msg *)buff;
490 switch(smp->si_type) {
491 case SCSP_CFG_RSP:
492 if (smp->si_rc != SCSP_RSP_OK) {
493 rc = EINVAL;
494 goto read_fail;
496 break;
497 case SCSP_CACHE_IND:
498 rc = atmarp_scsp_cache(aip, smp);
499 break;
500 case SCSP_SOLICIT_IND:
501 rc = atmarp_scsp_solicit(aip, smp);
502 break;
503 case SCSP_UPDATE_IND:
504 rc = atmarp_scsp_update_in(aip, smp);
505 break;
506 case SCSP_UPDATE_RSP:
508 * Ignore Update Responses
510 break;
511 default:
512 atmarp_log(LOG_ERR, "Unexpected SCSP message received");
513 return(EOPNOTSUPP);
516 UM_FREE(buff);
517 return(rc);
519 read_fail:
520 if (buff) {
521 UM_FREE(buff);
525 * Error on socket to SCSP--close the socket and set the state
526 * so that we know to retry when the cache timer fires.
528 atmarp_scsp_close(aip);
530 return(rc);
535 * Send a message to SCSP
538 * Arguments:
539 * aip pointer to ATMARP interface to send message on
540 * buff pointer to message buffer
541 * len length of message
543 * Returns:
544 * 0 message sent
545 * errno reason for failure
549 atmarp_scsp_out(Atmarp_intf *aip, char *buff, int len)
551 int rc;
554 * Send the message to SCSP
556 rc = write(aip->ai_scsp_sock, buff, len);
557 if (rc == len)
558 return(0);
561 * Error on write--close the socket to SCSP, clean up and
562 * set the state so that we know to retry when the cache
563 * timer fires.
565 atmarp_scsp_close(aip);
568 * Set the return code
570 if (rc < 0) {
571 rc = errno;
572 } else {
573 rc = EFAULT;
576 return(rc);
581 * Set up a socket and connect to SCSP
583 * Arguments:
584 * aip pointer to interface block
586 * Returns:
587 * 0 success, ai_scsp_sock is set
588 * errno reason for failure
593 atmarp_scsp_connect(Atmarp_intf *aip)
595 int len, rc, sd;
596 char *sn;
597 Scsp_if_msg cfg_msg;
599 static struct sockaddr local_addr = {
600 #if (defined(BSD) && (BSD >= 199103))
601 sizeof(struct sockaddr), /* sa_len */
602 #endif
603 AF_UNIX, /* sa_family */
604 ATMARP_SOCK_PREFIX /* sa_data */
606 static struct sockaddr scsp_addr = {
607 #if (defined(BSD) && (BSD >= 199103))
608 sizeof(struct sockaddr), /* sa_len */
609 #endif
610 AF_UNIX, /* sa_family */
611 SCSPD_SOCK_NAME /* sa_data */
615 * Construct a name for the socket
617 strncpy(local_addr.sa_data, ATMARP_SOCK_PREFIX,
618 sizeof(local_addr.sa_data));
619 strncat(local_addr.sa_data, aip->ai_intf, sizeof(local_addr.sa_data));
620 sn = strdup(local_addr.sa_data);
621 if (!sn)
622 atmarp_mem_err("atmarp_scsp_connect: strdup");
625 * Clean up any old socket
627 rc = unlink(sn);
628 if (rc < 0 && errno != ENOENT)
629 return(errno);
632 * Open a socket to SCSP
634 sd = socket(PF_UNIX, SOCK_STREAM, 0);
635 if (sd == -1) {
636 UM_FREE(sn);
637 return(errno);
639 if (sd > atmarp_max_socket) {
640 atmarp_max_socket = sd;
644 * Set non-blocking I/O
646 #ifdef sun
647 rc = fcntl(sd, F_SETFL, FNBIO + FNDELAY);
648 #else
649 rc = fcntl(sd, F_SETFL, O_NONBLOCK);
650 #endif
651 if (rc == -1) {
652 rc = errno;
653 goto scsp_connect_fail;
657 * Bind the local socket address
659 rc = bind(sd, &local_addr, sizeof(local_addr));
660 if (rc) {
661 rc = errno;
662 goto scsp_connect_fail;
666 * Connect to SCSP
668 rc = connect(sd, &scsp_addr, sizeof(scsp_addr));
669 if (rc) {
670 rc = errno;
671 goto scsp_connect_fail;
675 * Save socket information in interface control block
677 aip->ai_scsp_sock = sd;
678 aip->ai_scsp_sockname = sn;
679 aip->ai_state = AI_STATE_UP;
682 * Send configuration information to SCSP
684 UM_ZERO(&cfg_msg, sizeof(cfg_msg));
685 cfg_msg.si_type = SCSP_CFG_REQ;
686 cfg_msg.si_proto = SCSP_PROTO_ATMARP;
687 strcpy(cfg_msg.si_cfg.atmarp_netif, aip->ai_intf);
688 len =sizeof(Scsp_if_msg_hdr) + strlen(aip->ai_intf) + 1;
689 cfg_msg.si_len = len;
690 rc = atmarp_scsp_out(aip, (char *)&cfg_msg, len);
691 if (rc) {
692 return(rc);
695 return(0);
697 scsp_connect_fail:
698 close(sd);
699 aip->ai_scsp_sock = -1;
700 UM_FREE(sn);
701 aip->ai_scsp_sockname = NULL;
702 aip->ai_state = AI_STATE_NULL;
703 return(rc);
708 * Close a socket connection to SCSP
710 * Arguments:
711 * aip pointer to interface block for connection to be closed
713 * Returns:
714 * none
718 void
719 atmarp_scsp_close(Atmarp_intf *aip)
722 * Close and unlink the SCSP socket
724 close(aip->ai_scsp_sock);
725 aip->ai_scsp_sock = -1;
726 unlink(aip->ai_scsp_sockname);
727 UM_FREE(aip->ai_scsp_sockname);
728 aip->ai_scsp_sockname = NULL;
730 aip->ai_state = AI_STATE_NULL;
732 return;
737 * Disconnect an interface from SCSP
739 * Arguments:
740 * aip pointer to interface block for connection to be closed
742 * Returns:
743 * 0 success, ai_scsp_sock is set
744 * errno reason for failure
749 atmarp_scsp_disconnect(Atmarp_intf *aip)
751 int i;
752 Atmarp *aap;
755 * Close and unlink the SCSP socket
757 atmarp_scsp_close(aip);
760 * Free the ATMARP cache associated with the interface
762 for (i = 0; i < ATMARP_HASHSIZ; i++) {
763 for (aap = aip->ai_arptbl[i]; aap; aap = aap->aa_next) {
764 UM_FREE(aap);
766 aip->ai_arptbl[i] = NULL;
769 return(0);