123162Smckusick /* 229068Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423162Smckusick * 533183Sbostic * Redistribution and use in source and binary forms are permitted 634844Sbostic * provided that the above copyright notice and this paragraph are 734844Sbostic * duplicated in all such forms and that any documentation, 834844Sbostic * advertising materials, and other materials related to such 934844Sbostic * distribution and use acknowledge that the software was developed 1034844Sbostic * by the University of California, Berkeley. The name of the 1134844Sbostic * University may not be used to endorse or promote products derived 1234844Sbostic * from this software without specific prior written permission. 1334844Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434844Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534844Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633183Sbostic * 17*39181Ssklower * @(#)raw_usrreq.c 7.7 (Berkeley) 09/20/89 1823162Smckusick */ 195121Swnj 2017037Sbloom #include "param.h" 2117037Sbloom #include "mbuf.h" 2217037Sbloom #include "domain.h" 2317037Sbloom #include "protosw.h" 2417037Sbloom #include "socket.h" 2517037Sbloom #include "socketvar.h" 2617037Sbloom #include "errno.h" 2710890Ssam 2817037Sbloom #include "if.h" 2917037Sbloom #include "route.h" 3017037Sbloom #include "netisr.h" 3117037Sbloom #include "raw_cb.h" 325121Swnj 3337500Smckusick #include "machine/mtpr.h" 3410890Ssam 355121Swnj /* 365612Swnj * Initialize raw connection block q. 376211Swnj */ 385612Swnj raw_init() 395612Swnj { 406211Swnj 415612Swnj rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 426211Swnj rawintrq.ifq_maxlen = IFQ_MAXLEN; 435612Swnj } 445612Swnj 4537472Ssklower 465612Swnj /* 4737472Ssklower * Raw protocol input routine. Find the socket 4837472Ssklower * associated with the packet(s) and move them over. If 4937472Ssklower * nothing exists for this packet, drop it. 5037472Ssklower */ 5137472Ssklower /* 525121Swnj * Raw protocol interface. 535121Swnj */ 546529Ssam raw_input(m0, proto, src, dst) 555612Swnj struct mbuf *m0; 56*39181Ssklower register struct sockproto *proto; 576529Ssam struct sockaddr *src, *dst; 585121Swnj { 595612Swnj register struct rawcb *rp; 6037472Ssklower register struct mbuf *m = m0; 61*39181Ssklower register int sockets = 0; 625612Swnj struct socket *last; 635121Swnj 645612Swnj last = 0; 655612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 6637472Ssklower if (rp->rcb_proto.sp_family != proto->sp_family) 675612Swnj continue; 6821769Skarels if (rp->rcb_proto.sp_protocol && 6937472Ssklower rp->rcb_proto.sp_protocol != proto->sp_protocol) 705612Swnj continue; 715612Swnj /* 725612Swnj * We assume the lower level routines have 735612Swnj * placed the address in a canonical format 746509Ssam * suitable for a structure comparison. 7537472Ssklower * 7637472Ssklower * Note that if the lengths are not the same 7737472Ssklower * the comparison will fail at the first byte. 785612Swnj */ 7937472Ssklower #define equal(a1, a2) \ 8037472Ssklower (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 8137472Ssklower if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 825612Swnj continue; 8337472Ssklower if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 846509Ssam continue; 855612Swnj if (last) { 865612Swnj struct mbuf *n; 8737472Ssklower if (n = m_copy(m, 0, (int)M_COPYALL)) { 8837472Ssklower if (sbappendaddr(&last->so_rcv, src, 8921531Skarels n, (struct mbuf *)0) == 0) 9021531Skarels /* should notify about lost packet */ 9121531Skarels m_freem(n); 92*39181Ssklower else { 9321531Skarels sorwakeup(last); 94*39181Ssklower sockets++; 95*39181Ssklower } 965646Ssam } 975612Swnj } 986509Ssam last = rp->rcb_socket; 995612Swnj } 1006584Ssam if (last) { 10137472Ssklower if (sbappendaddr(&last->so_rcv, src, 10237472Ssklower m, (struct mbuf *)0) == 0) 10337472Ssklower m_freem(m); 104*39181Ssklower else { 10521531Skarels sorwakeup(last); 106*39181Ssklower sockets++; 107*39181Ssklower } 10821531Skarels } else 10921531Skarels m_freem(m); 110*39181Ssklower return (sockets); 1115121Swnj } 1125121Swnj 1138636Sroot /*ARGSUSED*/ 1146584Ssam raw_ctlinput(cmd, arg) 1156584Ssam int cmd; 11626379Skarels struct sockaddr *arg; 1176584Ssam { 1186591Ssam 1196591Ssam if (cmd < 0 || cmd > PRC_NCMDS) 1206591Ssam return; 1218636Sroot /* INCOMPLETE */ 1226584Ssam } 1236584Ssam 1245121Swnj /*ARGSUSED*/ 12537472Ssklower raw_usrreq(so, req, m, nam, rights, control) 1265121Swnj struct socket *so; 1275121Swnj int req; 12837472Ssklower struct mbuf *m, *nam, *rights, *control; 1295121Swnj { 1305612Swnj register struct rawcb *rp = sotorawcb(so); 13112783Ssam register int error = 0; 13237472Ssklower int len; 1335121Swnj 13425501Skarels if (req == PRU_CONTROL) 13525501Skarels return (EOPNOTSUPP); 13612783Ssam if (rights && rights->m_len) { 13712783Ssam error = EOPNOTSUPP; 13812783Ssam goto release; 13912783Ssam } 14037472Ssklower if (rp == 0) { 14112783Ssam error = EINVAL; 14212783Ssam goto release; 14312783Ssam } 1445612Swnj switch (req) { 1455612Swnj 1465612Swnj /* 1475612Swnj * Allocate a raw control block and fill in the 1485612Swnj * necessary info to allow packets to be routed to 1495612Swnj * the appropriate raw interface routine. 1505612Swnj */ 1515612Swnj case PRU_ATTACH: 15212783Ssam if ((so->so_state & SS_PRIV) == 0) { 15312783Ssam error = EACCES; 15413116Ssam break; 15512783Ssam } 15621769Skarels error = raw_attach(so, (int)nam); 1575612Swnj break; 1585612Swnj 1595612Swnj /* 1605612Swnj * Destroy state just before socket deallocation. 1615612Swnj * Flush data or not depending on the options. 1625612Swnj */ 1635612Swnj case PRU_DETACH: 16412783Ssam if (rp == 0) { 16512783Ssam error = ENOTCONN; 16613116Ssam break; 16712783Ssam } 1685612Swnj raw_detach(rp); 1695612Swnj break; 1705612Swnj 17137472Ssklower #ifdef notdef 1725612Swnj /* 1735612Swnj * If a socket isn't bound to a single address, 1745612Swnj * the raw input routine will hand it anything 1755612Swnj * within that protocol family (assuming there's 1765612Swnj * nothing else around it should go to). 1775612Swnj */ 1785612Swnj case PRU_CONNECT: 17937472Ssklower if (rp->rcb_faddr) { 18012783Ssam error = EISCONN; 18113116Ssam break; 18212783Ssam } 18337472Ssklower nam = m_copym(nam, 0, M_COPYALL, M_WAIT); 18437472Ssklower rp->rcb_faddr = mtod(nam, struct sockaddr *); 1855612Swnj soisconnected(so); 1865612Swnj break; 1875612Swnj 18812783Ssam case PRU_BIND: 18937472Ssklower if (rp->rcb_laddr) { 19012783Ssam error = EINVAL; /* XXX */ 19113116Ssam break; 19212783Ssam } 19312783Ssam error = raw_bind(so, nam); 19412783Ssam break; 19537472Ssklower #endif 19612783Ssam 19737472Ssklower case PRU_CONNECT2: 19837472Ssklower error = EOPNOTSUPP; 19937472Ssklower goto release; 20037472Ssklower 2015612Swnj case PRU_DISCONNECT: 20237472Ssklower if (rp->rcb_faddr == 0) { 20312783Ssam error = ENOTCONN; 20413116Ssam break; 20512783Ssam } 2065612Swnj raw_disconnect(rp); 2075612Swnj soisdisconnected(so); 2085612Swnj break; 2095612Swnj 2105612Swnj /* 2115612Swnj * Mark the connection as being incapable of further input. 2125612Swnj */ 2135612Swnj case PRU_SHUTDOWN: 2145612Swnj socantsendmore(so); 2155612Swnj break; 2165612Swnj 2175612Swnj /* 2185612Swnj * Ship a packet out. The appropriate raw output 2195612Swnj * routine handles any massaging necessary. 2205612Swnj */ 2215612Swnj case PRU_SEND: 2228395Swnj if (nam) { 22337472Ssklower if (rp->rcb_faddr) { 22412783Ssam error = EISCONN; 22513116Ssam break; 22612783Ssam } 22737472Ssklower rp->rcb_faddr = mtod(nam, struct sockaddr *); 22837472Ssklower } else if (rp->rcb_faddr == 0) { 22912783Ssam error = ENOTCONN; 23013116Ssam break; 23112783Ssam } 2326505Ssam error = (*so->so_proto->pr_output)(m, so); 23312783Ssam m = NULL; 2348395Swnj if (nam) 23537472Ssklower rp->rcb_faddr = 0; 2365612Swnj break; 2375612Swnj 2385612Swnj case PRU_ABORT: 2395612Swnj raw_disconnect(rp); 2405612Swnj sofree(so); 2415612Swnj soisdisconnected(so); 2425612Swnj break; 2435612Swnj 24416974Skarels case PRU_SENSE: 24516974Skarels /* 24616974Skarels * stat: don't bother with a blocksize. 24716974Skarels */ 24816974Skarels return (0); 24916974Skarels 2505612Swnj /* 2515612Swnj * Not supported. 2525612Swnj */ 25316773Sbloom case PRU_RCVOOB: 2545612Swnj case PRU_RCVD: 25516773Sbloom return(EOPNOTSUPP); 25616773Sbloom 25725221Skarels case PRU_LISTEN: 25816773Sbloom case PRU_ACCEPT: 2595612Swnj case PRU_SENDOOB: 2605612Swnj error = EOPNOTSUPP; 2615612Swnj break; 2625612Swnj 2636509Ssam case PRU_SOCKADDR: 26437472Ssklower if (rp->rcb_laddr == 0) { 26537472Ssklower error = EINVAL; 26637472Ssklower break; 26737472Ssklower } 26837472Ssklower len = rp->rcb_laddr->sa_len; 26937472Ssklower bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); 27037472Ssklower nam->m_len = len; 2716509Ssam break; 2726509Ssam 27314122Ssam case PRU_PEERADDR: 27437472Ssklower if (rp->rcb_faddr == 0) { 27537472Ssklower error = ENOTCONN; 27637472Ssklower break; 27737472Ssklower } 27837472Ssklower len = rp->rcb_faddr->sa_len; 27937472Ssklower bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); 28037472Ssklower nam->m_len = len; 28114122Ssam break; 28214122Ssam 2835612Swnj default: 2845612Swnj panic("raw_usrreq"); 2855612Swnj } 28612783Ssam release: 28712783Ssam if (m != NULL) 28812783Ssam m_freem(m); 2895612Swnj return (error); 2905121Swnj } 29137472Ssklower 29237472Ssklower rawintr() {} /* XXX - referenced by locore. will soon go away */ 293