1*39540Ssklower /* 2*39540Ssklower * Copyright (c) 1989 Regents of the University of California. 3*39540Ssklower * All rights reserved. 4*39540Ssklower * 5*39540Ssklower * Redistribution and use in source and binary forms are permitted 6*39540Ssklower * provided that the above copyright notice and this paragraph are 7*39540Ssklower * duplicated in all such forms and that any documentation, 8*39540Ssklower * advertising materials, and other materials related to such 9*39540Ssklower * distribution and use acknowledge that the software was developed 10*39540Ssklower * by the University of California, Berkeley. The name of the 11*39540Ssklower * University may not be used to endorse or promote products derived 12*39540Ssklower * from this software without specific prior written permission. 13*39540Ssklower * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*39540Ssklower * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*39540Ssklower * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*39540Ssklower * 17*39540Ssklower * @(#)cltp_usrreq.c 7.1 (Berkeley) 11/15/89 18*39540Ssklower */ 19*39540Ssklower 20*39540Ssklower #ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */ 21*39540Ssklower #include "param.h" 22*39540Ssklower #include "user.h" 23*39540Ssklower #include "malloc.h" 24*39540Ssklower #include "mbuf.h" 25*39540Ssklower #include "protosw.h" 26*39540Ssklower #include "socket.h" 27*39540Ssklower #include "socketvar.h" 28*39540Ssklower #include "errno.h" 29*39540Ssklower #include "stat.h" 30*39540Ssklower 31*39540Ssklower #include "../net/if.h" 32*39540Ssklower #include "../net/route.h" 33*39540Ssklower 34*39540Ssklower #include "argo_debug.h" 35*39540Ssklower #include "iso.h" 36*39540Ssklower #include "iso_pcb.h" 37*39540Ssklower #include "iso_var.h" 38*39540Ssklower #include "clnp.h" 39*39540Ssklower #include "cltp_var.h" 40*39540Ssklower #endif 41*39540Ssklower 42*39540Ssklower /* 43*39540Ssklower * CLTP protocol implementation. 44*39540Ssklower * Per ISO 8602, December, 1987. 45*39540Ssklower */ 46*39540Ssklower cltp_init() 47*39540Ssklower { 48*39540Ssklower 49*39540Ssklower cltb.isop_next = cltb.isop_prev = &cltb; 50*39540Ssklower } 51*39540Ssklower 52*39540Ssklower int cltp_cksum = 1; 53*39540Ssklower 54*39540Ssklower 55*39540Ssklower /* ARGUSED */ 56*39540Ssklower cltp_input(m0, srcsa, dstsa, cons_channel, output) 57*39540Ssklower struct mbuf *m0; 58*39540Ssklower struct sockaddr *srcsa, *dstsa; 59*39540Ssklower u_int cons_channel; 60*39540Ssklower int (*output)(); 61*39540Ssklower { 62*39540Ssklower register struct isopcb *isop; 63*39540Ssklower register struct mbuf *m = m0; 64*39540Ssklower register u_char *up = mtod(m, u_char *); 65*39540Ssklower register struct sockaddr_iso *src = (struct sockaddr_iso *)srcsa; 66*39540Ssklower int len, hdrlen = *up + 1, dlen = 0; 67*39540Ssklower u_char *uplim = up + hdrlen; 68*39540Ssklower caddr_t dtsap; 69*39540Ssklower 70*39540Ssklower for (len = 0; m; m = m->m_next) 71*39540Ssklower len += m->m_len; 72*39540Ssklower up += 2; /* skip header */ 73*39540Ssklower while (up < uplim) switch (*up) { /* process options */ 74*39540Ssklower case CLTPOVAL_SRC: 75*39540Ssklower src->siso_tlen = up[1]; 76*39540Ssklower src->siso_len = up[1] + TSEL(src) - (caddr_t)src; 77*39540Ssklower if (src->siso_len < sizeof(*src)) 78*39540Ssklower src->siso_len = sizeof(*src); 79*39540Ssklower else if (src->siso_len > sizeof(*src)) { 80*39540Ssklower MGET(m, M_DONTWAIT, MT_SONAME); 81*39540Ssklower if (m == 0) 82*39540Ssklower goto bad; 83*39540Ssklower m->m_len = src->siso_len; 84*39540Ssklower src = mtod(m, struct sockaddr_iso *); 85*39540Ssklower bcopy((caddr_t)srcsa, (caddr_t)src, srcsa->sa_len); 86*39540Ssklower } 87*39540Ssklower bcopy((caddr_t)up + 2, TSEL(src), up[1]); 88*39540Ssklower up += 2 + src->siso_tlen; 89*39540Ssklower continue; 90*39540Ssklower 91*39540Ssklower case CLTPOVAL_DST: 92*39540Ssklower dtsap = 2 + (caddr_t)up; 93*39540Ssklower dlen = up[1]; 94*39540Ssklower up += 2 + dlen; 95*39540Ssklower continue; 96*39540Ssklower 97*39540Ssklower case CLTPOVAL_CSM: 98*39540Ssklower if (iso_check_csum(m0, len)) 99*39540Ssklower goto bad; 100*39540Ssklower up += 4; 101*39540Ssklower 102*39540Ssklower default: 103*39540Ssklower printf("clts: unknown option (%x)\n", up[0]); 104*39540Ssklower goto bad; 105*39540Ssklower } 106*39540Ssklower if (dlen == 0 || src->siso_tlen == 0) 107*39540Ssklower goto bad; 108*39540Ssklower for (isop = cltb.isop_next;; isop = isop->isop_next) { 109*39540Ssklower if (isop == &cltb) 110*39540Ssklower goto bad; 111*39540Ssklower if (isop->isop_laddr && 112*39540Ssklower bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0) 113*39540Ssklower break; 114*39540Ssklower } 115*39540Ssklower m = m0; 116*39540Ssklower m->m_len += hdrlen; 117*39540Ssklower if (sbappendaddr(&isop->isop_socket->so_rcv, (struct sockaddr *)src, 118*39540Ssklower m, (struct mbuf *)0) == 0) 119*39540Ssklower goto bad; 120*39540Ssklower sorwakeup(isop->isop_socket); 121*39540Ssklower m0 = 0; 122*39540Ssklower bad: 123*39540Ssklower if (src != (struct sockaddr_iso *)srcsa) 124*39540Ssklower m_freem(dtom(src)); 125*39540Ssklower if (m0) 126*39540Ssklower m_freem(m0); 127*39540Ssklower return; 128*39540Ssklower } 129*39540Ssklower 130*39540Ssklower /* 131*39540Ssklower * Notify a cltp user of an asynchronous error; 132*39540Ssklower * just wake up so that he can collect error status. 133*39540Ssklower */ 134*39540Ssklower cltp_notify(isop) 135*39540Ssklower register struct isopcb *isop; 136*39540Ssklower { 137*39540Ssklower 138*39540Ssklower sorwakeup(isop->isop_socket); 139*39540Ssklower sowwakeup(isop->isop_socket); 140*39540Ssklower } 141*39540Ssklower 142*39540Ssklower cltp_ctlinput(cmd, sa) 143*39540Ssklower int cmd; 144*39540Ssklower struct sockaddr *sa; 145*39540Ssklower { 146*39540Ssklower extern u_char inetctlerrmap[]; 147*39540Ssklower struct sockaddr_iso *siso; 148*39540Ssklower int iso_rtchange(); 149*39540Ssklower 150*39540Ssklower if ((unsigned)cmd > PRC_NCMDS) 151*39540Ssklower return; 152*39540Ssklower if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT) 153*39540Ssklower return; 154*39540Ssklower siso = (struct sockaddr_iso *)sa; 155*39540Ssklower if (siso == 0 || siso->siso_nlen == 0) 156*39540Ssklower return; 157*39540Ssklower 158*39540Ssklower switch (cmd) { 159*39540Ssklower case PRC_ROUTEDEAD: 160*39540Ssklower case PRC_REDIRECT_NET: 161*39540Ssklower case PRC_REDIRECT_HOST: 162*39540Ssklower case PRC_REDIRECT_TOSNET: 163*39540Ssklower case PRC_REDIRECT_TOSHOST: 164*39540Ssklower iso_pcbnotify(&cltb, siso, 165*39540Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 166*39540Ssklower break; 167*39540Ssklower 168*39540Ssklower default: 169*39540Ssklower if (inetctlerrmap[cmd] == 0) 170*39540Ssklower return; /* XXX */ 171*39540Ssklower iso_pcbnotify(&cltb, siso, (int)inetctlerrmap[cmd], 172*39540Ssklower cltp_notify); 173*39540Ssklower } 174*39540Ssklower } 175*39540Ssklower 176*39540Ssklower cltp_output(isop, m) 177*39540Ssklower register struct isopcb *isop; 178*39540Ssklower register struct mbuf *m; 179*39540Ssklower { 180*39540Ssklower register int len; 181*39540Ssklower register struct sockaddr_iso *siso; 182*39540Ssklower int hdrlen, error = 0, docsum; 183*39540Ssklower register u_char *up; 184*39540Ssklower 185*39540Ssklower if (isop->isop_laddr == 0 || isop->isop_faddr == 0) { 186*39540Ssklower error = ENOTCONN; 187*39540Ssklower goto bad; 188*39540Ssklower } 189*39540Ssklower /* 190*39540Ssklower * Calculate data length and get a mbuf for CLTP header. 191*39540Ssklower */ 192*39540Ssklower hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen 193*39540Ssklower + 2 + isop->isop_faddr->siso_tlen; 194*39540Ssklower if (docsum = /*isop->isop_flags & CLNP_NO_CKSUM*/ cltp_cksum) 195*39540Ssklower hdrlen += 4; 196*39540Ssklower M_PREPEND(m, hdrlen, M_WAIT); 197*39540Ssklower len = m->m_pkthdr.len; 198*39540Ssklower /* 199*39540Ssklower * Fill in mbuf with extended CLTP header 200*39540Ssklower */ 201*39540Ssklower up = mtod(m, u_char *); 202*39540Ssklower up[0] = UD_TPDU_type; 203*39540Ssklower up[1] = hdrlen - 1; 204*39540Ssklower up[2] = CLTPOVAL_DST; 205*39540Ssklower up[3] = (siso = isop->isop_laddr)->siso_tlen; 206*39540Ssklower up += 4; 207*39540Ssklower bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen); 208*39540Ssklower up += siso->siso_tlen; 209*39540Ssklower up[0] = CLTPOVAL_SRC; 210*39540Ssklower up[1] = (siso = isop->isop_faddr)->siso_tlen; 211*39540Ssklower up += 2; 212*39540Ssklower bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen); 213*39540Ssklower /* 214*39540Ssklower * Stuff checksum and output datagram. 215*39540Ssklower */ 216*39540Ssklower if (docsum) { 217*39540Ssklower up += siso->siso_tlen; 218*39540Ssklower up[0] = CLTPOVAL_CSM; 219*39540Ssklower up[1] = 2; 220*39540Ssklower iso_gen_cksum(m, 2 + up - mtod(m, u_char *), len); 221*39540Ssklower } 222*39540Ssklower return (tpclnp_output(isop, m, len, !docsum)); 223*39540Ssklower bad: 224*39540Ssklower m_freem(m); 225*39540Ssklower return (error); 226*39540Ssklower } 227*39540Ssklower 228*39540Ssklower #ifndef TP_LOCAL 229*39540Ssklower /* XXXX should go in iso.h maybe? from tp_param.h, in any case */ 230*39540Ssklower #define TP_LOCAL 22 231*39540Ssklower #define TP_FOREIGN 33 232*39540Ssklower #endif 233*39540Ssklower 234*39540Ssklower u_long cltp_sendspace = 9216; /* really max datagram size */ 235*39540Ssklower u_long cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso)); 236*39540Ssklower /* 40 1K datagrams */ 237*39540Ssklower 238*39540Ssklower 239*39540Ssklower /*ARGSUSED*/ 240*39540Ssklower cltp_usrreq(so, req, m, nam, rights, control) 241*39540Ssklower struct socket *so; 242*39540Ssklower int req; 243*39540Ssklower struct mbuf *m, *nam, *rights, *control; 244*39540Ssklower { 245*39540Ssklower struct isopcb *isop = sotoisopcb(so); 246*39540Ssklower int s, error = 0; 247*39540Ssklower 248*39540Ssklower if (req == PRU_CONTROL) 249*39540Ssklower return (iso_control(so, (int)m, (caddr_t)nam, 250*39540Ssklower (struct ifnet *)rights)); 251*39540Ssklower if (rights && rights->m_len) { 252*39540Ssklower error = EINVAL; 253*39540Ssklower goto release; 254*39540Ssklower } 255*39540Ssklower if (isop == NULL && req != PRU_ATTACH) { 256*39540Ssklower error = EINVAL; 257*39540Ssklower goto release; 258*39540Ssklower } 259*39540Ssklower switch (req) { 260*39540Ssklower 261*39540Ssklower case PRU_ATTACH: 262*39540Ssklower if (isop != NULL) { 263*39540Ssklower error = EINVAL; 264*39540Ssklower break; 265*39540Ssklower } 266*39540Ssklower error = iso_pcballoc(so, &cltb); 267*39540Ssklower if (error) 268*39540Ssklower break; 269*39540Ssklower error = soreserve(so, cltp_sendspace, cltp_recvspace); 270*39540Ssklower if (error) 271*39540Ssklower break; 272*39540Ssklower break; 273*39540Ssklower 274*39540Ssklower case PRU_DETACH: 275*39540Ssklower iso_pcbdetach(isop); 276*39540Ssklower break; 277*39540Ssklower 278*39540Ssklower case PRU_BIND: 279*39540Ssklower error = iso_pcbbind(isop, nam); 280*39540Ssklower break; 281*39540Ssklower 282*39540Ssklower case PRU_LISTEN: 283*39540Ssklower error = EOPNOTSUPP; 284*39540Ssklower break; 285*39540Ssklower 286*39540Ssklower case PRU_CONNECT: 287*39540Ssklower if (isop->isop_faddr) { 288*39540Ssklower error = EISCONN; 289*39540Ssklower break; 290*39540Ssklower } 291*39540Ssklower error = iso_pcbconnect(isop, nam); 292*39540Ssklower if (error == 0) 293*39540Ssklower soisconnected(so); 294*39540Ssklower break; 295*39540Ssklower 296*39540Ssklower case PRU_CONNECT2: 297*39540Ssklower error = EOPNOTSUPP; 298*39540Ssklower break; 299*39540Ssklower 300*39540Ssklower case PRU_ACCEPT: 301*39540Ssklower error = EOPNOTSUPP; 302*39540Ssklower break; 303*39540Ssklower 304*39540Ssklower case PRU_DISCONNECT: 305*39540Ssklower if (isop->isop_faddr == 0) { 306*39540Ssklower error = ENOTCONN; 307*39540Ssklower break; 308*39540Ssklower } 309*39540Ssklower iso_pcbdisconnect(isop); 310*39540Ssklower so->so_state &= ~SS_ISCONNECTED; /* XXX */ 311*39540Ssklower break; 312*39540Ssklower 313*39540Ssklower case PRU_SHUTDOWN: 314*39540Ssklower socantsendmore(so); 315*39540Ssklower break; 316*39540Ssklower 317*39540Ssklower case PRU_SEND: 318*39540Ssklower if (nam) { 319*39540Ssklower if (isop->isop_faddr) { 320*39540Ssklower error = EISCONN; 321*39540Ssklower break; 322*39540Ssklower } 323*39540Ssklower /* 324*39540Ssklower * Must block input while temporarily connected. 325*39540Ssklower */ 326*39540Ssklower s = splnet(); 327*39540Ssklower error = iso_pcbconnect(isop, nam); 328*39540Ssklower if (error) { 329*39540Ssklower splx(s); 330*39540Ssklower break; 331*39540Ssklower } 332*39540Ssklower } else { 333*39540Ssklower if (isop->isop_faddr == 0) { 334*39540Ssklower error = ENOTCONN; 335*39540Ssklower break; 336*39540Ssklower } 337*39540Ssklower } 338*39540Ssklower error = cltp_output(isop, m); 339*39540Ssklower m = 0; 340*39540Ssklower if (nam) { 341*39540Ssklower iso_pcbdisconnect(isop); 342*39540Ssklower splx(s); 343*39540Ssklower } 344*39540Ssklower break; 345*39540Ssklower 346*39540Ssklower case PRU_ABORT: 347*39540Ssklower soisdisconnected(so); 348*39540Ssklower iso_pcbdetach(isop); 349*39540Ssklower break; 350*39540Ssklower 351*39540Ssklower case PRU_SOCKADDR: 352*39540Ssklower iso_getnetaddr(isop, nam, TP_LOCAL); 353*39540Ssklower break; 354*39540Ssklower 355*39540Ssklower case PRU_PEERADDR: 356*39540Ssklower iso_getnetaddr(isop, nam, TP_FOREIGN); 357*39540Ssklower break; 358*39540Ssklower 359*39540Ssklower case PRU_SENSE: 360*39540Ssklower /* 361*39540Ssklower * stat: don't bother with a blocksize. 362*39540Ssklower */ 363*39540Ssklower return (0); 364*39540Ssklower 365*39540Ssklower case PRU_SENDOOB: 366*39540Ssklower case PRU_FASTTIMO: 367*39540Ssklower case PRU_SLOWTIMO: 368*39540Ssklower case PRU_PROTORCV: 369*39540Ssklower case PRU_PROTOSEND: 370*39540Ssklower error = EOPNOTSUPP; 371*39540Ssklower break; 372*39540Ssklower 373*39540Ssklower case PRU_RCVD: 374*39540Ssklower case PRU_RCVOOB: 375*39540Ssklower return (EOPNOTSUPP); /* do not free mbuf's */ 376*39540Ssklower 377*39540Ssklower default: 378*39540Ssklower panic("cltp_usrreq"); 379*39540Ssklower } 380*39540Ssklower release: 381*39540Ssklower if (m != NULL) 382*39540Ssklower m_freem(m); 383*39540Ssklower return (error); 384*39540Ssklower } 385