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/sys/netatm/uni/uniarp_output.c,v 1.3 1999/08/28 00:49:03 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp_output.c,v 1.3 2003/08/07 21:17:35 dillon Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577) - Output packet processing
38 #include <netatm/kern_include.h>
40 #include <netatm/ipatm/ipatm_var.h>
41 #include <netatm/ipatm/ipatm_serv.h>
42 #include "uniip_var.h"
45 * Issue an ATMARP Request PDU
48 * uip pointer to IP interface
49 * tip pointer to target IP address
52 * 0 PDU was successfully sent
53 * else unable to send PDU
57 uniarp_arp_req(uip, tip)
62 struct atmarp_hdr *ahp;
72 sip = inp->inf_nif->nif_pif->pif_siginst;
75 * Figure out how long pdu is going to be
77 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
78 switch (sip->si_addr.address_format) {
79 case T_ATM_ENDSYS_ADDR:
80 len += sip->si_addr.address_length;
84 len += sip->si_addr.address_length;
85 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
86 len += sip->si_subaddr.address_length;
91 * Get a buffer for pdu
93 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
98 * Place aligned pdu at end of buffer
100 KB_TAILALIGN(m, len);
101 KB_DATASTART(m, ahp, struct atmarp_hdr *);
104 * Setup variable fields pointer
106 cp = (char *)ahp + sizeof(struct atmarp_hdr);
111 ahp->ah_hrd = htons(ARP_ATMFORUM);
112 ahp->ah_pro = htons(ETHERTYPE_IP);
113 len = sip->si_addr.address_length;
114 switch (sip->si_addr.address_format) {
115 case T_ATM_ENDSYS_ADDR:
116 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
119 KM_COPY(sip->si_addr.address, cp, len - 1);
120 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
126 case T_ATM_E164_ADDR:
127 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
130 KM_COPY(sip->si_addr.address, cp, len);
133 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
134 len = sip->si_subaddr.address_length;
135 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
138 KM_COPY(sip->si_subaddr.address, cp, len - 1);
139 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
150 ahp->ah_op = htons(ARP_REQUEST);
151 ahp->ah_spln = sizeof(struct in_addr);
154 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
155 sizeof(struct in_addr));
156 cp += sizeof(struct in_addr);
161 ahp->ah_tpln = sizeof(struct in_addr);
164 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
167 * Finally, send the pdu to the ATMARP server
169 ivp = uip->uip_arpsvrvcc;
171 uniarp_pdu_print(ivp, m, "send");
172 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
186 * Issue an ATMARP Response PDU
189 * uip pointer to IP interface
190 * amp pointer to source map entry
191 * tip pointer to target IP address
192 * tatm pointer to target ATM address
193 * tsub pointer to target ATM subaddress
194 * ivp pointer to vcc over which to send pdu
197 * 0 PDU was successfully sent
198 * else unable to send PDU
202 uniarp_arp_rsp(uip, amp, tip, tatm, tsub, ivp)
211 struct atmarp_hdr *ahp;
216 * Figure out how long pdu is going to be
218 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
219 switch (amp->am_dstatm.address_format) {
220 case T_ATM_ENDSYS_ADDR:
221 len += amp->am_dstatm.address_length;
224 case T_ATM_E164_ADDR:
225 len += amp->am_dstatm.address_length;
226 if (amp->am_dstatmsub.address_format == T_ATM_ENDSYS_ADDR)
227 len += amp->am_dstatmsub.address_length;
231 switch (tatm->address_format) {
232 case T_ATM_ENDSYS_ADDR:
233 len += tatm->address_length;
236 case T_ATM_E164_ADDR:
237 len += tatm->address_length;
238 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
239 len += tsub->address_length;
244 * Get a buffer for pdu
246 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
251 * Place aligned pdu at end of buffer
253 KB_TAILALIGN(m, len);
254 KB_DATASTART(m, ahp, struct atmarp_hdr *);
257 * Setup variable fields pointer
259 cp = (char *)ahp + sizeof(struct atmarp_hdr);
264 ahp->ah_hrd = htons(ARP_ATMFORUM);
265 ahp->ah_pro = htons(ETHERTYPE_IP);
266 len = amp->am_dstatm.address_length;
267 switch (amp->am_dstatm.address_format) {
268 case T_ATM_ENDSYS_ADDR:
269 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
272 KM_COPY(amp->am_dstatm.address, cp, len);
278 case T_ATM_E164_ADDR:
279 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
282 KM_COPY(amp->am_dstatm.address, cp, len);
285 if (amp->am_dstatmsub.address_format == T_ATM_ENDSYS_ADDR) {
286 len = amp->am_dstatmsub.address_length;
287 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
290 KM_COPY(amp->am_dstatmsub.address, cp, len);
301 ahp->ah_op = htons(ARP_REPLY);
302 ahp->ah_spln = sizeof(struct in_addr);
305 KM_COPY((caddr_t)&->am_dstip, cp, sizeof(struct in_addr));
306 cp += sizeof(struct in_addr);
308 len = tatm->address_length;
309 switch (tatm->address_format) {
310 case T_ATM_ENDSYS_ADDR:
311 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
314 KM_COPY(tatm->address, cp, len);
320 case T_ATM_E164_ADDR:
321 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
324 KM_COPY(tatm->address, cp, len);
327 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
328 len = tsub->address_length;
329 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
332 KM_COPY(tsub->address, cp, len);
343 ahp->ah_tpln = sizeof(struct in_addr);
346 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
349 * Finally, send the pdu to the vcc peer
352 uniarp_pdu_print(ivp, m, "send");
353 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
367 * Issue an ATMARP NAK PDU
370 * uip pointer to IP interface
371 * m pointer to ATMARP_REQ buffer chain
372 * ivp pointer to vcc over which to send pdu
375 * 0 PDU was successfully sent
376 * else unable to send PDU
380 uniarp_arp_nak(uip, m, ivp)
385 struct atmarp_hdr *ahp;
389 * Get the fixed fields together
391 if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
392 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
396 KB_DATASTART(m, ahp, struct atmarp_hdr *);
401 ahp->ah_op = htons(ARP_NAK);
404 * Finally, send the pdu to the vcc peer
407 uniarp_pdu_print(ivp, m, "send");
408 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
422 * Issue an InATMARP Request PDU
425 * uip pointer to IP interface
426 * tatm pointer to target ATM address
427 * tsub pointer to target ATM subaddress
428 * ivp pointer to vcc over which to send pdu
431 * 0 PDU was successfully sent
432 * else unable to send PDU
436 uniarp_inarp_req(uip, tatm, tsub, ivp)
443 struct atmarp_hdr *ahp;
450 inp = uip->uip_ipnif;
452 sip = inp->inf_nif->nif_pif->pif_siginst;
455 * Figure out how long pdu is going to be
457 len = sizeof(struct atmarp_hdr) + sizeof(struct in_addr);
458 switch (sip->si_addr.address_format) {
459 case T_ATM_ENDSYS_ADDR:
460 len += sip->si_addr.address_length;
463 case T_ATM_E164_ADDR:
464 len += sip->si_addr.address_length;
465 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
466 len += sip->si_subaddr.address_length;
470 switch (tatm->address_format) {
471 case T_ATM_ENDSYS_ADDR:
472 len += tatm->address_length;
475 case T_ATM_E164_ADDR:
476 len += tatm->address_length;
477 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
478 len += tsub->address_length;
483 * Get a buffer for pdu
485 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
490 * Place aligned pdu at end of buffer
492 KB_TAILALIGN(m, len);
493 KB_DATASTART(m, ahp, struct atmarp_hdr *);
496 * Setup variable fields pointer
498 cp = (char *)ahp + sizeof(struct atmarp_hdr);
503 ahp->ah_hrd = htons(ARP_ATMFORUM);
504 ahp->ah_pro = htons(ETHERTYPE_IP);
505 len = sip->si_addr.address_length;
506 switch (sip->si_addr.address_format) {
507 case T_ATM_ENDSYS_ADDR:
508 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
511 KM_COPY(sip->si_addr.address, cp, len - 1);
512 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
518 case T_ATM_E164_ADDR:
519 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
522 KM_COPY(sip->si_addr.address, cp, len);
525 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
526 len = sip->si_subaddr.address_length;
527 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
530 KM_COPY(sip->si_subaddr.address, cp, len - 1);
531 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
542 ahp->ah_op = htons(INARP_REQUEST);
543 ahp->ah_spln = sizeof(struct in_addr);
546 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
547 sizeof(struct in_addr));
548 cp += sizeof(struct in_addr);
550 len = tatm->address_length;
551 switch (tatm->address_format) {
552 case T_ATM_ENDSYS_ADDR:
553 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
556 KM_COPY(tatm->address, cp, len);
562 case T_ATM_E164_ADDR:
563 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
566 KM_COPY(tatm->address, cp, len);
569 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
570 len = tsub->address_length;
571 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
574 KM_COPY(tsub->address, cp, len);
588 * Finally, send the pdu to the vcc peer
591 uniarp_pdu_print(ivp, m, "send");
592 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
606 * Issue an InATMARP Response PDU
609 * uip pointer to IP interface
610 * tip pointer to target IP address
611 * tatm pointer to target ATM address
612 * tsub pointer to target ATM subaddress
613 * ivp pointer to vcc over which to send pdu
616 * 0 PDU was successfully sent
617 * else unable to send PDU
621 uniarp_inarp_rsp(uip, tip, tatm, tsub, ivp)
629 struct atmarp_hdr *ahp;
636 inp = uip->uip_ipnif;
638 sip = inp->inf_nif->nif_pif->pif_siginst;
641 * Figure out how long pdu is going to be
643 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
644 switch (sip->si_addr.address_format) {
645 case T_ATM_ENDSYS_ADDR:
646 len += sip->si_addr.address_length;
649 case T_ATM_E164_ADDR:
650 len += sip->si_addr.address_length;
651 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
652 len += sip->si_subaddr.address_length;
656 switch (tatm->address_format) {
657 case T_ATM_ENDSYS_ADDR:
658 len += tatm->address_length;
661 case T_ATM_E164_ADDR:
662 len += tatm->address_length;
663 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
664 len += tsub->address_length;
669 * Get a buffer for pdu
671 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
676 * Place aligned pdu at end of buffer
678 KB_TAILALIGN(m, len);
679 KB_DATASTART(m, ahp, struct atmarp_hdr *);
682 * Setup variable fields pointer
684 cp = (char *)ahp + sizeof(struct atmarp_hdr);
689 ahp->ah_hrd = htons(ARP_ATMFORUM);
690 ahp->ah_pro = htons(ETHERTYPE_IP);
691 len = sip->si_addr.address_length;
692 switch (sip->si_addr.address_format) {
693 case T_ATM_ENDSYS_ADDR:
694 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
697 KM_COPY(sip->si_addr.address, cp, len - 1);
698 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
704 case T_ATM_E164_ADDR:
705 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
708 KM_COPY(sip->si_addr.address, cp, len);
711 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
712 len = sip->si_subaddr.address_length;
713 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
716 KM_COPY(sip->si_subaddr.address, cp, len - 1);
717 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
728 ahp->ah_op = htons(INARP_REPLY);
729 ahp->ah_spln = sizeof(struct in_addr);
732 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
733 sizeof(struct in_addr));
734 cp += sizeof(struct in_addr);
736 len = tatm->address_length;
737 switch (tatm->address_format) {
738 case T_ATM_ENDSYS_ADDR:
739 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
742 KM_COPY(tatm->address, cp, len);
748 case T_ATM_E164_ADDR:
749 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
752 KM_COPY(tatm->address, cp, len);
755 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
756 len = tsub->address_length;
757 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
760 KM_COPY(tsub->address, cp, len);
771 ahp->ah_tpln = sizeof(struct in_addr);
774 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
777 * Finally, send the pdu to the vcc peer
780 uniarp_pdu_print(ivp, m, "send");
781 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);