139540Ssklower /* 239540Ssklower * Copyright (c) 1989 Regents of the University of California. 339540Ssklower * All rights reserved. 439540Ssklower * 544495Sbostic * %sccs.include.redist.c% 639540Ssklower * 7*56533Sbostic * @(#)cltp_usrreq.c 7.9 (Berkeley) 10/11/92 839540Ssklower */ 939540Ssklower 1039540Ssklower #ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */ 11*56533Sbostic #include <sys/param.h> 12*56533Sbostic #include <sys/malloc.h> 13*56533Sbostic #include <sys/mbuf.h> 14*56533Sbostic #include <sys/protosw.h> 15*56533Sbostic #include <sys/socket.h> 16*56533Sbostic #include <sys/socketvar.h> 17*56533Sbostic #include <sys/errno.h> 18*56533Sbostic #include <sys/stat.h> 1939540Ssklower 20*56533Sbostic #include <net/if.h> 21*56533Sbostic #include <net/route.h> 2239540Ssklower 23*56533Sbostic #include <netiso/argo_debug.h> 24*56533Sbostic #include <netiso/iso.h> 25*56533Sbostic #include <netiso/iso_pcb.h> 26*56533Sbostic #include <netiso/iso_var.h> 27*56533Sbostic #include <netiso/clnp.h> 28*56533Sbostic #include <netiso/cltp_var.h> 2939540Ssklower #endif 3039540Ssklower 3139540Ssklower /* 3239540Ssklower * CLTP protocol implementation. 3339540Ssklower * Per ISO 8602, December, 1987. 3439540Ssklower */ 3539540Ssklower cltp_init() 3639540Ssklower { 3739540Ssklower 3839540Ssklower cltb.isop_next = cltb.isop_prev = &cltb; 3939540Ssklower } 4039540Ssklower 4139540Ssklower int cltp_cksum = 1; 4239540Ssklower 4339540Ssklower 4439540Ssklower /* ARGUSED */ 4539540Ssklower cltp_input(m0, srcsa, dstsa, cons_channel, output) 4639540Ssklower struct mbuf *m0; 4739540Ssklower struct sockaddr *srcsa, *dstsa; 4839540Ssklower u_int cons_channel; 4939540Ssklower int (*output)(); 5039540Ssklower { 5139540Ssklower register struct isopcb *isop; 5239540Ssklower register struct mbuf *m = m0; 5339540Ssklower register u_char *up = mtod(m, u_char *); 5439540Ssklower register struct sockaddr_iso *src = (struct sockaddr_iso *)srcsa; 5539540Ssklower int len, hdrlen = *up + 1, dlen = 0; 5639540Ssklower u_char *uplim = up + hdrlen; 5739540Ssklower caddr_t dtsap; 5839540Ssklower 5939540Ssklower for (len = 0; m; m = m->m_next) 6039540Ssklower len += m->m_len; 6139540Ssklower up += 2; /* skip header */ 6239540Ssklower while (up < uplim) switch (*up) { /* process options */ 6339540Ssklower case CLTPOVAL_SRC: 6439540Ssklower src->siso_tlen = up[1]; 6539540Ssklower src->siso_len = up[1] + TSEL(src) - (caddr_t)src; 6639540Ssklower if (src->siso_len < sizeof(*src)) 6739540Ssklower src->siso_len = sizeof(*src); 6839540Ssklower else if (src->siso_len > sizeof(*src)) { 6939540Ssklower MGET(m, M_DONTWAIT, MT_SONAME); 7039540Ssklower if (m == 0) 7139540Ssklower goto bad; 7239540Ssklower m->m_len = src->siso_len; 7339540Ssklower src = mtod(m, struct sockaddr_iso *); 7439540Ssklower bcopy((caddr_t)srcsa, (caddr_t)src, srcsa->sa_len); 7539540Ssklower } 7639540Ssklower bcopy((caddr_t)up + 2, TSEL(src), up[1]); 7739540Ssklower up += 2 + src->siso_tlen; 7839540Ssklower continue; 7939540Ssklower 8039540Ssklower case CLTPOVAL_DST: 8139540Ssklower dtsap = 2 + (caddr_t)up; 8239540Ssklower dlen = up[1]; 8339540Ssklower up += 2 + dlen; 8439540Ssklower continue; 8539540Ssklower 8639540Ssklower case CLTPOVAL_CSM: 8739925Ssklower if (iso_check_csum(m0, len)) { 8839925Ssklower cltpstat.cltps_badsum++; 8939540Ssklower goto bad; 9039925Ssklower } 9139540Ssklower up += 4; 9239925Ssklower continue; 9339540Ssklower 9439540Ssklower default: 9539540Ssklower printf("clts: unknown option (%x)\n", up[0]); 9639925Ssklower cltpstat.cltps_hdrops++; 9739540Ssklower goto bad; 9839540Ssklower } 9939540Ssklower if (dlen == 0 || src->siso_tlen == 0) 10039540Ssklower goto bad; 10139540Ssklower for (isop = cltb.isop_next;; isop = isop->isop_next) { 10239925Ssklower if (isop == &cltb) { 10339925Ssklower cltpstat.cltps_noport++; 10439540Ssklower goto bad; 10539925Ssklower } 10639540Ssklower if (isop->isop_laddr && 10739540Ssklower bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0) 10839540Ssklower break; 10939540Ssklower } 11039540Ssklower m = m0; 11139925Ssklower m->m_len -= hdrlen; 11239925Ssklower m->m_data += hdrlen; 11339540Ssklower if (sbappendaddr(&isop->isop_socket->so_rcv, (struct sockaddr *)src, 11439540Ssklower m, (struct mbuf *)0) == 0) 11539540Ssklower goto bad; 11639925Ssklower cltpstat.cltps_ipackets++; 11739540Ssklower sorwakeup(isop->isop_socket); 11839540Ssklower m0 = 0; 11939540Ssklower bad: 12039540Ssklower if (src != (struct sockaddr_iso *)srcsa) 12139540Ssklower m_freem(dtom(src)); 12239540Ssklower if (m0) 12339540Ssklower m_freem(m0); 12439925Ssklower return 0; 12539540Ssklower } 12639540Ssklower 12739540Ssklower /* 12839540Ssklower * Notify a cltp user of an asynchronous error; 12939540Ssklower * just wake up so that he can collect error status. 13039540Ssklower */ 13139540Ssklower cltp_notify(isop) 13239540Ssklower register struct isopcb *isop; 13339540Ssklower { 13439540Ssklower 13539540Ssklower sorwakeup(isop->isop_socket); 13639540Ssklower sowwakeup(isop->isop_socket); 13739540Ssklower } 13839540Ssklower 13939540Ssklower cltp_ctlinput(cmd, sa) 14039540Ssklower int cmd; 14139540Ssklower struct sockaddr *sa; 14239540Ssklower { 14339540Ssklower extern u_char inetctlerrmap[]; 14439540Ssklower struct sockaddr_iso *siso; 14539540Ssklower int iso_rtchange(); 14639540Ssklower 14739540Ssklower if ((unsigned)cmd > PRC_NCMDS) 14839540Ssklower return; 14939540Ssklower if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT) 15039540Ssklower return; 15139540Ssklower siso = (struct sockaddr_iso *)sa; 15239540Ssklower if (siso == 0 || siso->siso_nlen == 0) 15339540Ssklower return; 15439540Ssklower 15539540Ssklower switch (cmd) { 15639540Ssklower case PRC_ROUTEDEAD: 15739540Ssklower case PRC_REDIRECT_NET: 15839540Ssklower case PRC_REDIRECT_HOST: 15939540Ssklower case PRC_REDIRECT_TOSNET: 16039540Ssklower case PRC_REDIRECT_TOSHOST: 16139540Ssklower iso_pcbnotify(&cltb, siso, 16239540Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 16339540Ssklower break; 16439540Ssklower 16539540Ssklower default: 16639540Ssklower if (inetctlerrmap[cmd] == 0) 16739540Ssklower return; /* XXX */ 16839540Ssklower iso_pcbnotify(&cltb, siso, (int)inetctlerrmap[cmd], 16939540Ssklower cltp_notify); 17039540Ssklower } 17139540Ssklower } 17239540Ssklower 17339540Ssklower cltp_output(isop, m) 17439540Ssklower register struct isopcb *isop; 17539540Ssklower register struct mbuf *m; 17639540Ssklower { 17739540Ssklower register int len; 17839540Ssklower register struct sockaddr_iso *siso; 17939540Ssklower int hdrlen, error = 0, docsum; 18039540Ssklower register u_char *up; 18139540Ssklower 18239540Ssklower if (isop->isop_laddr == 0 || isop->isop_faddr == 0) { 18339540Ssklower error = ENOTCONN; 18439540Ssklower goto bad; 18539540Ssklower } 18639540Ssklower /* 18739540Ssklower * Calculate data length and get a mbuf for CLTP header. 18839540Ssklower */ 18939540Ssklower hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen 19039540Ssklower + 2 + isop->isop_faddr->siso_tlen; 19139540Ssklower if (docsum = /*isop->isop_flags & CLNP_NO_CKSUM*/ cltp_cksum) 19239540Ssklower hdrlen += 4; 19339540Ssklower M_PREPEND(m, hdrlen, M_WAIT); 19439540Ssklower len = m->m_pkthdr.len; 19539540Ssklower /* 19639540Ssklower * Fill in mbuf with extended CLTP header 19739540Ssklower */ 19839540Ssklower up = mtod(m, u_char *); 19939925Ssklower up[0] = hdrlen - 1; 20039925Ssklower up[1] = UD_TPDU_type; 20139925Ssklower up[2] = CLTPOVAL_SRC; 20239540Ssklower up[3] = (siso = isop->isop_laddr)->siso_tlen; 20339540Ssklower up += 4; 20439540Ssklower bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen); 20539540Ssklower up += siso->siso_tlen; 20639925Ssklower up[0] = CLTPOVAL_DST; 20739540Ssklower up[1] = (siso = isop->isop_faddr)->siso_tlen; 20839540Ssklower up += 2; 20939540Ssklower bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen); 21039540Ssklower /* 21139540Ssklower * Stuff checksum and output datagram. 21239540Ssklower */ 21339540Ssklower if (docsum) { 21439540Ssklower up += siso->siso_tlen; 21539540Ssklower up[0] = CLTPOVAL_CSM; 21639540Ssklower up[1] = 2; 21739925Ssklower iso_gen_csum(m, 2 + up - mtod(m, u_char *), len); 21839540Ssklower } 21939925Ssklower cltpstat.cltps_opackets++; 22039540Ssklower return (tpclnp_output(isop, m, len, !docsum)); 22139540Ssklower bad: 22239540Ssklower m_freem(m); 22339540Ssklower return (error); 22439540Ssklower } 22539540Ssklower 22639540Ssklower u_long cltp_sendspace = 9216; /* really max datagram size */ 22739540Ssklower u_long cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso)); 22839540Ssklower /* 40 1K datagrams */ 22939540Ssklower 23039540Ssklower 23139540Ssklower /*ARGSUSED*/ 23240771Ssklower cltp_usrreq(so, req, m, nam, control) 23339540Ssklower struct socket *so; 23439540Ssklower int req; 23540771Ssklower struct mbuf *m, *nam, *control; 23639540Ssklower { 23750432Ssklower register struct isopcb *isop = sotoisopcb(so); 23839540Ssklower int s, error = 0; 23939540Ssklower 24039540Ssklower if (req == PRU_CONTROL) 24139540Ssklower return (iso_control(so, (int)m, (caddr_t)nam, 24240771Ssklower (struct ifnet *)control)); 24341925Ssklower if ((isop == NULL && req != PRU_ATTACH) || 24441925Ssklower (control && control->m_len)) { 24539540Ssklower error = EINVAL; 24639540Ssklower goto release; 24739540Ssklower } 24839540Ssklower switch (req) { 24939540Ssklower 25039540Ssklower case PRU_ATTACH: 25139540Ssklower if (isop != NULL) { 25239540Ssklower error = EINVAL; 25339540Ssklower break; 25439540Ssklower } 25539540Ssklower error = iso_pcballoc(so, &cltb); 25639540Ssklower if (error) 25739540Ssklower break; 25839540Ssklower error = soreserve(so, cltp_sendspace, cltp_recvspace); 25939540Ssklower if (error) 26039540Ssklower break; 26139540Ssklower break; 26239540Ssklower 26339540Ssklower case PRU_DETACH: 26439540Ssklower iso_pcbdetach(isop); 26539540Ssklower break; 26639540Ssklower 26739540Ssklower case PRU_BIND: 26839540Ssklower error = iso_pcbbind(isop, nam); 26939540Ssklower break; 27039540Ssklower 27139540Ssklower case PRU_LISTEN: 27239540Ssklower error = EOPNOTSUPP; 27339540Ssklower break; 27439540Ssklower 27539540Ssklower case PRU_CONNECT: 27639540Ssklower if (isop->isop_faddr) { 27739540Ssklower error = EISCONN; 27839540Ssklower break; 27939540Ssklower } 28039540Ssklower error = iso_pcbconnect(isop, nam); 28139540Ssklower if (error == 0) 28239540Ssklower soisconnected(so); 28339540Ssklower break; 28439540Ssklower 28539540Ssklower case PRU_CONNECT2: 28639540Ssklower error = EOPNOTSUPP; 28739540Ssklower break; 28839540Ssklower 28939540Ssklower case PRU_ACCEPT: 29039540Ssklower error = EOPNOTSUPP; 29139540Ssklower break; 29239540Ssklower 29339540Ssklower case PRU_DISCONNECT: 29439540Ssklower if (isop->isop_faddr == 0) { 29539540Ssklower error = ENOTCONN; 29639540Ssklower break; 29739540Ssklower } 29839540Ssklower iso_pcbdisconnect(isop); 29939540Ssklower so->so_state &= ~SS_ISCONNECTED; /* XXX */ 30039540Ssklower break; 30139540Ssklower 30239540Ssklower case PRU_SHUTDOWN: 30339540Ssklower socantsendmore(so); 30439540Ssklower break; 30539540Ssklower 30639540Ssklower case PRU_SEND: 30739540Ssklower if (nam) { 30839540Ssklower if (isop->isop_faddr) { 30939540Ssklower error = EISCONN; 31039540Ssklower break; 31139540Ssklower } 31239540Ssklower /* 31339540Ssklower * Must block input while temporarily connected. 31439540Ssklower */ 31539540Ssklower s = splnet(); 31639540Ssklower error = iso_pcbconnect(isop, nam); 31739540Ssklower if (error) { 31839540Ssklower splx(s); 31939540Ssklower break; 32039540Ssklower } 32139540Ssklower } else { 32239540Ssklower if (isop->isop_faddr == 0) { 32339540Ssklower error = ENOTCONN; 32439540Ssklower break; 32539540Ssklower } 32639540Ssklower } 32739540Ssklower error = cltp_output(isop, m); 32839540Ssklower m = 0; 32939540Ssklower if (nam) { 33039540Ssklower iso_pcbdisconnect(isop); 33139540Ssklower splx(s); 33239540Ssklower } 33339540Ssklower break; 33439540Ssklower 33539540Ssklower case PRU_ABORT: 33639540Ssklower soisdisconnected(so); 33739540Ssklower iso_pcbdetach(isop); 33839540Ssklower break; 33939540Ssklower 34039540Ssklower case PRU_SOCKADDR: 34150432Ssklower if (isop->isop_laddr) 34250432Ssklower bcopy((caddr_t)isop->isop_laddr, mtod(m, caddr_t), 34350432Ssklower nam->m_len = isop->isop_laddr->siso_len); 34439540Ssklower break; 34539540Ssklower 34639540Ssklower case PRU_PEERADDR: 34750432Ssklower if (isop->isop_faddr) 34850432Ssklower bcopy((caddr_t)isop->isop_faddr, mtod(m, caddr_t), 34950432Ssklower nam->m_len = isop->isop_faddr->siso_len); 35039540Ssklower break; 35139540Ssklower 35239540Ssklower case PRU_SENSE: 35339540Ssklower /* 35439540Ssklower * stat: don't bother with a blocksize. 35539540Ssklower */ 35639540Ssklower return (0); 35739540Ssklower 35839540Ssklower case PRU_SENDOOB: 35939540Ssklower case PRU_FASTTIMO: 36039540Ssklower case PRU_SLOWTIMO: 36139540Ssklower case PRU_PROTORCV: 36239540Ssklower case PRU_PROTOSEND: 36339540Ssklower error = EOPNOTSUPP; 36439540Ssklower break; 36539540Ssklower 36639540Ssklower case PRU_RCVD: 36739540Ssklower case PRU_RCVOOB: 36839540Ssklower return (EOPNOTSUPP); /* do not free mbuf's */ 36939540Ssklower 37039540Ssklower default: 37139540Ssklower panic("cltp_usrreq"); 37239540Ssklower } 37339540Ssklower release: 37441925Ssklower if (control != NULL) 37541925Ssklower m_freem(control); 37639540Ssklower if (m != NULL) 37739540Ssklower m_freem(m); 37839540Ssklower return (error); 37939540Ssklower } 380