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