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 $
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 <netatm/uni/uniip_var.h>
45 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/uniarp_output.c,v 1.3 1999/08/28 00:49:03 peter Exp $");
50 * Issue an ATMARP Request PDU
53 * uip pointer to IP interface
54 * tip pointer to target IP address
57 * 0 PDU was successfully sent
58 * else unable to send PDU
62 uniarp_arp_req(uip, tip)
67 struct atmarp_hdr *ahp;
77 sip = inp->inf_nif->nif_pif->pif_siginst;
80 * Figure out how long pdu is going to be
82 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
83 switch (sip->si_addr.address_format) {
84 case T_ATM_ENDSYS_ADDR:
85 len += sip->si_addr.address_length;
89 len += sip->si_addr.address_length;
90 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
91 len += sip->si_subaddr.address_length;
96 * Get a buffer for pdu
98 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
103 * Place aligned pdu at end of buffer
105 KB_TAILALIGN(m, len);
106 KB_DATASTART(m, ahp, struct atmarp_hdr *);
109 * Setup variable fields pointer
111 cp = (char *)ahp + sizeof(struct atmarp_hdr);
116 ahp->ah_hrd = htons(ARP_ATMFORUM);
117 ahp->ah_pro = htons(ETHERTYPE_IP);
118 len = sip->si_addr.address_length;
119 switch (sip->si_addr.address_format) {
120 case T_ATM_ENDSYS_ADDR:
121 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
124 KM_COPY(sip->si_addr.address, cp, len - 1);
125 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
131 case T_ATM_E164_ADDR:
132 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
135 KM_COPY(sip->si_addr.address, cp, len);
138 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
139 len = sip->si_subaddr.address_length;
140 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
143 KM_COPY(sip->si_subaddr.address, cp, len - 1);
144 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
155 ahp->ah_op = htons(ARP_REQUEST);
156 ahp->ah_spln = sizeof(struct in_addr);
159 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
160 sizeof(struct in_addr));
161 cp += sizeof(struct in_addr);
166 ahp->ah_tpln = sizeof(struct in_addr);
169 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
172 * Finally, send the pdu to the ATMARP server
174 ivp = uip->uip_arpsvrvcc;
176 uniarp_pdu_print(ivp, m, "send");
177 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
191 * Issue an ATMARP Response PDU
194 * uip pointer to IP interface
195 * amp pointer to source map entry
196 * tip pointer to target IP address
197 * tatm pointer to target ATM address
198 * tsub pointer to target ATM subaddress
199 * ivp pointer to vcc over which to send pdu
202 * 0 PDU was successfully sent
203 * else unable to send PDU
207 uniarp_arp_rsp(uip, amp, tip, tatm, tsub, ivp)
216 struct atmarp_hdr *ahp;
221 * Figure out how long pdu is going to be
223 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
224 switch (amp->am_dstatm.address_format) {
225 case T_ATM_ENDSYS_ADDR:
226 len += amp->am_dstatm.address_length;
229 case T_ATM_E164_ADDR:
230 len += amp->am_dstatm.address_length;
231 if (amp->am_dstatmsub.address_format == T_ATM_ENDSYS_ADDR)
232 len += amp->am_dstatmsub.address_length;
236 switch (tatm->address_format) {
237 case T_ATM_ENDSYS_ADDR:
238 len += tatm->address_length;
241 case T_ATM_E164_ADDR:
242 len += tatm->address_length;
243 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
244 len += tsub->address_length;
249 * Get a buffer for pdu
251 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
256 * Place aligned pdu at end of buffer
258 KB_TAILALIGN(m, len);
259 KB_DATASTART(m, ahp, struct atmarp_hdr *);
262 * Setup variable fields pointer
264 cp = (char *)ahp + sizeof(struct atmarp_hdr);
269 ahp->ah_hrd = htons(ARP_ATMFORUM);
270 ahp->ah_pro = htons(ETHERTYPE_IP);
271 len = amp->am_dstatm.address_length;
272 switch (amp->am_dstatm.address_format) {
273 case T_ATM_ENDSYS_ADDR:
274 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
277 KM_COPY(amp->am_dstatm.address, cp, len);
283 case T_ATM_E164_ADDR:
284 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
287 KM_COPY(amp->am_dstatm.address, cp, len);
290 if (amp->am_dstatmsub.address_format == T_ATM_ENDSYS_ADDR) {
291 len = amp->am_dstatmsub.address_length;
292 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
295 KM_COPY(amp->am_dstatmsub.address, cp, len);
306 ahp->ah_op = htons(ARP_REPLY);
307 ahp->ah_spln = sizeof(struct in_addr);
310 KM_COPY((caddr_t)&->am_dstip, cp, sizeof(struct in_addr));
311 cp += sizeof(struct in_addr);
313 len = tatm->address_length;
314 switch (tatm->address_format) {
315 case T_ATM_ENDSYS_ADDR:
316 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
319 KM_COPY(tatm->address, cp, len);
325 case T_ATM_E164_ADDR:
326 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
329 KM_COPY(tatm->address, cp, len);
332 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
333 len = tsub->address_length;
334 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
337 KM_COPY(tsub->address, cp, len);
348 ahp->ah_tpln = sizeof(struct in_addr);
351 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
354 * Finally, send the pdu to the vcc peer
357 uniarp_pdu_print(ivp, m, "send");
358 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
372 * Issue an ATMARP NAK PDU
375 * uip pointer to IP interface
376 * m pointer to ATMARP_REQ buffer chain
377 * ivp pointer to vcc over which to send pdu
380 * 0 PDU was successfully sent
381 * else unable to send PDU
385 uniarp_arp_nak(uip, m, ivp)
390 struct atmarp_hdr *ahp;
394 * Get the fixed fields together
396 if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
397 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
401 KB_DATASTART(m, ahp, struct atmarp_hdr *);
406 ahp->ah_op = htons(ARP_NAK);
409 * Finally, send the pdu to the vcc peer
412 uniarp_pdu_print(ivp, m, "send");
413 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
427 * Issue an InATMARP Request PDU
430 * uip pointer to IP interface
431 * tatm pointer to target ATM address
432 * tsub pointer to target ATM subaddress
433 * ivp pointer to vcc over which to send pdu
436 * 0 PDU was successfully sent
437 * else unable to send PDU
441 uniarp_inarp_req(uip, tatm, tsub, ivp)
448 struct atmarp_hdr *ahp;
455 inp = uip->uip_ipnif;
457 sip = inp->inf_nif->nif_pif->pif_siginst;
460 * Figure out how long pdu is going to be
462 len = sizeof(struct atmarp_hdr) + sizeof(struct in_addr);
463 switch (sip->si_addr.address_format) {
464 case T_ATM_ENDSYS_ADDR:
465 len += sip->si_addr.address_length;
468 case T_ATM_E164_ADDR:
469 len += sip->si_addr.address_length;
470 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
471 len += sip->si_subaddr.address_length;
475 switch (tatm->address_format) {
476 case T_ATM_ENDSYS_ADDR:
477 len += tatm->address_length;
480 case T_ATM_E164_ADDR:
481 len += tatm->address_length;
482 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
483 len += tsub->address_length;
488 * Get a buffer for pdu
490 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
495 * Place aligned pdu at end of buffer
497 KB_TAILALIGN(m, len);
498 KB_DATASTART(m, ahp, struct atmarp_hdr *);
501 * Setup variable fields pointer
503 cp = (char *)ahp + sizeof(struct atmarp_hdr);
508 ahp->ah_hrd = htons(ARP_ATMFORUM);
509 ahp->ah_pro = htons(ETHERTYPE_IP);
510 len = sip->si_addr.address_length;
511 switch (sip->si_addr.address_format) {
512 case T_ATM_ENDSYS_ADDR:
513 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
516 KM_COPY(sip->si_addr.address, cp, len - 1);
517 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
523 case T_ATM_E164_ADDR:
524 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
527 KM_COPY(sip->si_addr.address, cp, len);
530 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
531 len = sip->si_subaddr.address_length;
532 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
535 KM_COPY(sip->si_subaddr.address, cp, len - 1);
536 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
547 ahp->ah_op = htons(INARP_REQUEST);
548 ahp->ah_spln = sizeof(struct in_addr);
551 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
552 sizeof(struct in_addr));
553 cp += sizeof(struct in_addr);
555 len = tatm->address_length;
556 switch (tatm->address_format) {
557 case T_ATM_ENDSYS_ADDR:
558 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
561 KM_COPY(tatm->address, cp, len);
567 case T_ATM_E164_ADDR:
568 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
571 KM_COPY(tatm->address, cp, len);
574 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
575 len = tsub->address_length;
576 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
579 KM_COPY(tsub->address, cp, len);
593 * Finally, send the pdu to the vcc peer
596 uniarp_pdu_print(ivp, m, "send");
597 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
611 * Issue an InATMARP Response PDU
614 * uip pointer to IP interface
615 * tip pointer to target IP address
616 * tatm pointer to target ATM address
617 * tsub pointer to target ATM subaddress
618 * ivp pointer to vcc over which to send pdu
621 * 0 PDU was successfully sent
622 * else unable to send PDU
626 uniarp_inarp_rsp(uip, tip, tatm, tsub, ivp)
634 struct atmarp_hdr *ahp;
641 inp = uip->uip_ipnif;
643 sip = inp->inf_nif->nif_pif->pif_siginst;
646 * Figure out how long pdu is going to be
648 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
649 switch (sip->si_addr.address_format) {
650 case T_ATM_ENDSYS_ADDR:
651 len += sip->si_addr.address_length;
654 case T_ATM_E164_ADDR:
655 len += sip->si_addr.address_length;
656 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
657 len += sip->si_subaddr.address_length;
661 switch (tatm->address_format) {
662 case T_ATM_ENDSYS_ADDR:
663 len += tatm->address_length;
666 case T_ATM_E164_ADDR:
667 len += tatm->address_length;
668 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
669 len += tsub->address_length;
674 * Get a buffer for pdu
676 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
681 * Place aligned pdu at end of buffer
683 KB_TAILALIGN(m, len);
684 KB_DATASTART(m, ahp, struct atmarp_hdr *);
687 * Setup variable fields pointer
689 cp = (char *)ahp + sizeof(struct atmarp_hdr);
694 ahp->ah_hrd = htons(ARP_ATMFORUM);
695 ahp->ah_pro = htons(ETHERTYPE_IP);
696 len = sip->si_addr.address_length;
697 switch (sip->si_addr.address_format) {
698 case T_ATM_ENDSYS_ADDR:
699 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
702 KM_COPY(sip->si_addr.address, cp, len - 1);
703 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
709 case T_ATM_E164_ADDR:
710 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
713 KM_COPY(sip->si_addr.address, cp, len);
716 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
717 len = sip->si_subaddr.address_length;
718 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
721 KM_COPY(sip->si_subaddr.address, cp, len - 1);
722 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
733 ahp->ah_op = htons(INARP_REPLY);
734 ahp->ah_spln = sizeof(struct in_addr);
737 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
738 sizeof(struct in_addr));
739 cp += sizeof(struct in_addr);
741 len = tatm->address_length;
742 switch (tatm->address_format) {
743 case T_ATM_ENDSYS_ADDR:
744 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
747 KM_COPY(tatm->address, cp, len);
753 case T_ATM_E164_ADDR:
754 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
757 KM_COPY(tatm->address, cp, len);
760 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
761 len = tsub->address_length;
762 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
765 KM_COPY(tsub->address, cp, len);
776 ahp->ah_tpln = sizeof(struct in_addr);
779 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
782 * Finally, send the pdu to the vcc peer
785 uniarp_pdu_print(ivp, m, "send");
786 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);