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.5 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577) - Output packet processing
38 #include <netproto/atm/kern_include.h>
40 #include <netproto/atm/ipatm/ipatm_var.h>
41 #include <netproto/atm/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(struct uniip *uip, struct in_addr *tip)
60 struct atmarp_hdr *ahp;
70 sip = inp->inf_nif->nif_pif->pif_siginst;
73 * Figure out how long pdu is going to be
75 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
76 switch (sip->si_addr.address_format) {
77 case T_ATM_ENDSYS_ADDR:
78 len += sip->si_addr.address_length;
82 len += sip->si_addr.address_length;
83 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
84 len += sip->si_subaddr.address_length;
89 * Get a buffer for pdu
91 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
96 * Place aligned pdu at end of buffer
99 KB_DATASTART(m, ahp, struct atmarp_hdr *);
102 * Setup variable fields pointer
104 cp = (char *)ahp + sizeof(struct atmarp_hdr);
109 ahp->ah_hrd = htons(ARP_ATMFORUM);
110 ahp->ah_pro = htons(ETHERTYPE_IP);
111 len = sip->si_addr.address_length;
112 switch (sip->si_addr.address_format) {
113 case T_ATM_ENDSYS_ADDR:
114 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
117 KM_COPY(sip->si_addr.address, cp, len - 1);
118 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
124 case T_ATM_E164_ADDR:
125 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
128 KM_COPY(sip->si_addr.address, cp, len);
131 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
132 len = sip->si_subaddr.address_length;
133 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
136 KM_COPY(sip->si_subaddr.address, cp, len - 1);
137 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
148 ahp->ah_op = htons(ARP_REQUEST);
149 ahp->ah_spln = sizeof(struct in_addr);
152 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
153 sizeof(struct in_addr));
154 cp += sizeof(struct in_addr);
159 ahp->ah_tpln = sizeof(struct in_addr);
162 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
165 * Finally, send the pdu to the ATMARP server
167 ivp = uip->uip_arpsvrvcc;
169 uniarp_pdu_print(ivp, m, "send");
170 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
184 * Issue an ATMARP Response PDU
187 * uip pointer to IP interface
188 * amp pointer to source map entry
189 * tip pointer to target IP address
190 * tatm pointer to target ATM address
191 * tsub pointer to target ATM subaddress
192 * ivp pointer to vcc over which to send pdu
195 * 0 PDU was successfully sent
196 * else unable to send PDU
200 uniarp_arp_rsp(struct uniip *uip, struct arpmap *amp, struct in_addr *tip,
201 Atm_addr *tatm, Atm_addr *tsub, struct ipvcc *ivp)
204 struct atmarp_hdr *ahp;
209 * Figure out how long pdu is going to be
211 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
212 switch (amp->am_dstatm.address_format) {
213 case T_ATM_ENDSYS_ADDR:
214 len += amp->am_dstatm.address_length;
217 case T_ATM_E164_ADDR:
218 len += amp->am_dstatm.address_length;
219 if (amp->am_dstatmsub.address_format == T_ATM_ENDSYS_ADDR)
220 len += amp->am_dstatmsub.address_length;
224 switch (tatm->address_format) {
225 case T_ATM_ENDSYS_ADDR:
226 len += tatm->address_length;
229 case T_ATM_E164_ADDR:
230 len += tatm->address_length;
231 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
232 len += tsub->address_length;
237 * Get a buffer for pdu
239 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
244 * Place aligned pdu at end of buffer
246 KB_TAILALIGN(m, len);
247 KB_DATASTART(m, ahp, struct atmarp_hdr *);
250 * Setup variable fields pointer
252 cp = (char *)ahp + sizeof(struct atmarp_hdr);
257 ahp->ah_hrd = htons(ARP_ATMFORUM);
258 ahp->ah_pro = htons(ETHERTYPE_IP);
259 len = amp->am_dstatm.address_length;
260 switch (amp->am_dstatm.address_format) {
261 case T_ATM_ENDSYS_ADDR:
262 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
265 KM_COPY(amp->am_dstatm.address, cp, len);
271 case T_ATM_E164_ADDR:
272 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
275 KM_COPY(amp->am_dstatm.address, cp, len);
278 if (amp->am_dstatmsub.address_format == T_ATM_ENDSYS_ADDR) {
279 len = amp->am_dstatmsub.address_length;
280 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
283 KM_COPY(amp->am_dstatmsub.address, cp, len);
294 ahp->ah_op = htons(ARP_REPLY);
295 ahp->ah_spln = sizeof(struct in_addr);
298 KM_COPY((caddr_t)&->am_dstip, cp, sizeof(struct in_addr));
299 cp += sizeof(struct in_addr);
301 len = tatm->address_length;
302 switch (tatm->address_format) {
303 case T_ATM_ENDSYS_ADDR:
304 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
307 KM_COPY(tatm->address, cp, len);
313 case T_ATM_E164_ADDR:
314 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
317 KM_COPY(tatm->address, cp, len);
320 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
321 len = tsub->address_length;
322 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
325 KM_COPY(tsub->address, cp, len);
336 ahp->ah_tpln = sizeof(struct in_addr);
339 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
342 * Finally, send the pdu to the vcc peer
345 uniarp_pdu_print(ivp, m, "send");
346 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
360 * Issue an ATMARP NAK PDU
363 * uip pointer to IP interface
364 * m pointer to ATMARP_REQ buffer chain
365 * ivp pointer to vcc over which to send pdu
368 * 0 PDU was successfully sent
369 * else unable to send PDU
373 uniarp_arp_nak(struct uniip *uip, KBuffer *m, struct ipvcc *ivp)
375 struct atmarp_hdr *ahp;
379 * Get the fixed fields together
381 if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
382 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
386 KB_DATASTART(m, ahp, struct atmarp_hdr *);
391 ahp->ah_op = htons(ARP_NAK);
394 * Finally, send the pdu to the vcc peer
397 uniarp_pdu_print(ivp, m, "send");
398 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
412 * Issue an InATMARP Request PDU
415 * uip pointer to IP interface
416 * tatm pointer to target ATM address
417 * tsub pointer to target ATM subaddress
418 * ivp pointer to vcc over which to send pdu
421 * 0 PDU was successfully sent
422 * else unable to send PDU
426 uniarp_inarp_req(struct uniip *uip, Atm_addr *tatm, Atm_addr *tsub,
430 struct atmarp_hdr *ahp;
437 inp = uip->uip_ipnif;
439 sip = inp->inf_nif->nif_pif->pif_siginst;
442 * Figure out how long pdu is going to be
444 len = sizeof(struct atmarp_hdr) + sizeof(struct in_addr);
445 switch (sip->si_addr.address_format) {
446 case T_ATM_ENDSYS_ADDR:
447 len += sip->si_addr.address_length;
450 case T_ATM_E164_ADDR:
451 len += sip->si_addr.address_length;
452 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
453 len += sip->si_subaddr.address_length;
457 switch (tatm->address_format) {
458 case T_ATM_ENDSYS_ADDR:
459 len += tatm->address_length;
462 case T_ATM_E164_ADDR:
463 len += tatm->address_length;
464 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
465 len += tsub->address_length;
470 * Get a buffer for pdu
472 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
477 * Place aligned pdu at end of buffer
479 KB_TAILALIGN(m, len);
480 KB_DATASTART(m, ahp, struct atmarp_hdr *);
483 * Setup variable fields pointer
485 cp = (char *)ahp + sizeof(struct atmarp_hdr);
490 ahp->ah_hrd = htons(ARP_ATMFORUM);
491 ahp->ah_pro = htons(ETHERTYPE_IP);
492 len = sip->si_addr.address_length;
493 switch (sip->si_addr.address_format) {
494 case T_ATM_ENDSYS_ADDR:
495 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
498 KM_COPY(sip->si_addr.address, cp, len - 1);
499 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
505 case T_ATM_E164_ADDR:
506 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
509 KM_COPY(sip->si_addr.address, cp, len);
512 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
513 len = sip->si_subaddr.address_length;
514 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
517 KM_COPY(sip->si_subaddr.address, cp, len - 1);
518 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
529 ahp->ah_op = htons(INARP_REQUEST);
530 ahp->ah_spln = sizeof(struct in_addr);
533 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
534 sizeof(struct in_addr));
535 cp += sizeof(struct in_addr);
537 len = tatm->address_length;
538 switch (tatm->address_format) {
539 case T_ATM_ENDSYS_ADDR:
540 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
543 KM_COPY(tatm->address, cp, len);
549 case T_ATM_E164_ADDR:
550 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
553 KM_COPY(tatm->address, cp, len);
556 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
557 len = tsub->address_length;
558 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
561 KM_COPY(tsub->address, cp, len);
575 * Finally, send the pdu to the vcc peer
578 uniarp_pdu_print(ivp, m, "send");
579 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
593 * Issue an InATMARP Response PDU
596 * uip pointer to IP interface
597 * tip pointer to target IP address
598 * tatm pointer to target ATM address
599 * tsub pointer to target ATM subaddress
600 * ivp pointer to vcc over which to send pdu
603 * 0 PDU was successfully sent
604 * else unable to send PDU
608 uniarp_inarp_rsp(struct uniip *uip, struct in_addr *tip, Atm_addr *tatm,
609 Atm_addr *tsub, struct ipvcc *ivp)
612 struct atmarp_hdr *ahp;
619 inp = uip->uip_ipnif;
621 sip = inp->inf_nif->nif_pif->pif_siginst;
624 * Figure out how long pdu is going to be
626 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
627 switch (sip->si_addr.address_format) {
628 case T_ATM_ENDSYS_ADDR:
629 len += sip->si_addr.address_length;
632 case T_ATM_E164_ADDR:
633 len += sip->si_addr.address_length;
634 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
635 len += sip->si_subaddr.address_length;
639 switch (tatm->address_format) {
640 case T_ATM_ENDSYS_ADDR:
641 len += tatm->address_length;
644 case T_ATM_E164_ADDR:
645 len += tatm->address_length;
646 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
647 len += tsub->address_length;
652 * Get a buffer for pdu
654 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
659 * Place aligned pdu at end of buffer
661 KB_TAILALIGN(m, len);
662 KB_DATASTART(m, ahp, struct atmarp_hdr *);
665 * Setup variable fields pointer
667 cp = (char *)ahp + sizeof(struct atmarp_hdr);
672 ahp->ah_hrd = htons(ARP_ATMFORUM);
673 ahp->ah_pro = htons(ETHERTYPE_IP);
674 len = sip->si_addr.address_length;
675 switch (sip->si_addr.address_format) {
676 case T_ATM_ENDSYS_ADDR:
677 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
680 KM_COPY(sip->si_addr.address, cp, len - 1);
681 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
687 case T_ATM_E164_ADDR:
688 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
691 KM_COPY(sip->si_addr.address, cp, len);
694 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
695 len = sip->si_subaddr.address_length;
696 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
699 KM_COPY(sip->si_subaddr.address, cp, len - 1);
700 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
711 ahp->ah_op = htons(INARP_REPLY);
712 ahp->ah_spln = sizeof(struct in_addr);
715 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
716 sizeof(struct in_addr));
717 cp += sizeof(struct in_addr);
719 len = tatm->address_length;
720 switch (tatm->address_format) {
721 case T_ATM_ENDSYS_ADDR:
722 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
725 KM_COPY(tatm->address, cp, len);
731 case T_ATM_E164_ADDR:
732 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
735 KM_COPY(tatm->address, cp, len);
738 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
739 len = tsub->address_length;
740 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
743 KM_COPY(tsub->address, cp, len);
754 ahp->ah_tpln = sizeof(struct in_addr);
757 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
760 * Finally, send the pdu to the vcc peer
763 uniarp_pdu_print(ivp, m, "send");
764 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);