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*37500Smckusick * @(#)raw_usrreq.c 7.6 (Berkeley) 04/25/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 33*37500Smckusick #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; 566509Ssam struct sockproto *proto; 576529Ssam struct sockaddr *src, *dst; 585121Swnj { 595612Swnj register struct rawcb *rp; 6037472Ssklower register struct mbuf *m = m0; 615612Swnj struct socket *last; 625121Swnj 635612Swnj last = 0; 645612Swnj for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 6537472Ssklower if (rp->rcb_proto.sp_family != proto->sp_family) 665612Swnj continue; 6721769Skarels if (rp->rcb_proto.sp_protocol && 6837472Ssklower rp->rcb_proto.sp_protocol != proto->sp_protocol) 695612Swnj continue; 705612Swnj /* 715612Swnj * We assume the lower level routines have 725612Swnj * placed the address in a canonical format 736509Ssam * suitable for a structure comparison. 7437472Ssklower * 7537472Ssklower * Note that if the lengths are not the same 7637472Ssklower * the comparison will fail at the first byte. 775612Swnj */ 7837472Ssklower #define equal(a1, a2) \ 7937472Ssklower (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 8037472Ssklower if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 815612Swnj continue; 8237472Ssklower if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 836509Ssam continue; 845612Swnj if (last) { 855612Swnj struct mbuf *n; 8637472Ssklower if (n = m_copy(m, 0, (int)M_COPYALL)) { 8737472Ssklower if (sbappendaddr(&last->so_rcv, src, 8821531Skarels n, (struct mbuf *)0) == 0) 8921531Skarels /* should notify about lost packet */ 9021531Skarels m_freem(n); 9121531Skarels else 9221531Skarels sorwakeup(last); 935646Ssam } 945612Swnj } 956509Ssam last = rp->rcb_socket; 965612Swnj } 976584Ssam if (last) { 9837472Ssklower if (sbappendaddr(&last->so_rcv, src, 9937472Ssklower m, (struct mbuf *)0) == 0) 10037472Ssklower m_freem(m); 10121531Skarels else 10221531Skarels sorwakeup(last); 10321531Skarels } else 10421531Skarels m_freem(m); 1055121Swnj } 1065121Swnj 1078636Sroot /*ARGSUSED*/ 1086584Ssam raw_ctlinput(cmd, arg) 1096584Ssam int cmd; 11026379Skarels struct sockaddr *arg; 1116584Ssam { 1126591Ssam 1136591Ssam if (cmd < 0 || cmd > PRC_NCMDS) 1146591Ssam return; 1158636Sroot /* INCOMPLETE */ 1166584Ssam } 1176584Ssam 1185121Swnj /*ARGSUSED*/ 11937472Ssklower raw_usrreq(so, req, m, nam, rights, control) 1205121Swnj struct socket *so; 1215121Swnj int req; 12237472Ssklower struct mbuf *m, *nam, *rights, *control; 1235121Swnj { 1245612Swnj register struct rawcb *rp = sotorawcb(so); 12512783Ssam register int error = 0; 12637472Ssklower int len; 1275121Swnj 12825501Skarels if (req == PRU_CONTROL) 12925501Skarels return (EOPNOTSUPP); 13012783Ssam if (rights && rights->m_len) { 13112783Ssam error = EOPNOTSUPP; 13212783Ssam goto release; 13312783Ssam } 13437472Ssklower if (rp == 0) { 13512783Ssam error = EINVAL; 13612783Ssam goto release; 13712783Ssam } 1385612Swnj switch (req) { 1395612Swnj 1405612Swnj /* 1415612Swnj * Allocate a raw control block and fill in the 1425612Swnj * necessary info to allow packets to be routed to 1435612Swnj * the appropriate raw interface routine. 1445612Swnj */ 1455612Swnj case PRU_ATTACH: 14612783Ssam if ((so->so_state & SS_PRIV) == 0) { 14712783Ssam error = EACCES; 14813116Ssam break; 14912783Ssam } 15021769Skarels error = raw_attach(so, (int)nam); 1515612Swnj break; 1525612Swnj 1535612Swnj /* 1545612Swnj * Destroy state just before socket deallocation. 1555612Swnj * Flush data or not depending on the options. 1565612Swnj */ 1575612Swnj case PRU_DETACH: 15812783Ssam if (rp == 0) { 15912783Ssam error = ENOTCONN; 16013116Ssam break; 16112783Ssam } 1625612Swnj raw_detach(rp); 1635612Swnj break; 1645612Swnj 16537472Ssklower #ifdef notdef 1665612Swnj /* 1675612Swnj * If a socket isn't bound to a single address, 1685612Swnj * the raw input routine will hand it anything 1695612Swnj * within that protocol family (assuming there's 1705612Swnj * nothing else around it should go to). 1715612Swnj */ 1725612Swnj case PRU_CONNECT: 17337472Ssklower if (rp->rcb_faddr) { 17412783Ssam error = EISCONN; 17513116Ssam break; 17612783Ssam } 17737472Ssklower nam = m_copym(nam, 0, M_COPYALL, M_WAIT); 17837472Ssklower rp->rcb_faddr = mtod(nam, struct sockaddr *); 1795612Swnj soisconnected(so); 1805612Swnj break; 1815612Swnj 18212783Ssam case PRU_BIND: 18337472Ssklower if (rp->rcb_laddr) { 18412783Ssam error = EINVAL; /* XXX */ 18513116Ssam break; 18612783Ssam } 18712783Ssam error = raw_bind(so, nam); 18812783Ssam break; 18937472Ssklower #endif 19012783Ssam 19137472Ssklower case PRU_CONNECT2: 19237472Ssklower error = EOPNOTSUPP; 19337472Ssklower goto release; 19437472Ssklower 1955612Swnj case PRU_DISCONNECT: 19637472Ssklower if (rp->rcb_faddr == 0) { 19712783Ssam error = ENOTCONN; 19813116Ssam break; 19912783Ssam } 2005612Swnj raw_disconnect(rp); 2015612Swnj soisdisconnected(so); 2025612Swnj break; 2035612Swnj 2045612Swnj /* 2055612Swnj * Mark the connection as being incapable of further input. 2065612Swnj */ 2075612Swnj case PRU_SHUTDOWN: 2085612Swnj socantsendmore(so); 2095612Swnj break; 2105612Swnj 2115612Swnj /* 2125612Swnj * Ship a packet out. The appropriate raw output 2135612Swnj * routine handles any massaging necessary. 2145612Swnj */ 2155612Swnj case PRU_SEND: 2168395Swnj if (nam) { 21737472Ssklower if (rp->rcb_faddr) { 21812783Ssam error = EISCONN; 21913116Ssam break; 22012783Ssam } 22137472Ssklower rp->rcb_faddr = mtod(nam, struct sockaddr *); 22237472Ssklower } else if (rp->rcb_faddr == 0) { 22312783Ssam error = ENOTCONN; 22413116Ssam break; 22512783Ssam } 2266505Ssam error = (*so->so_proto->pr_output)(m, so); 22712783Ssam m = NULL; 2288395Swnj if (nam) 22937472Ssklower rp->rcb_faddr = 0; 2305612Swnj break; 2315612Swnj 2325612Swnj case PRU_ABORT: 2335612Swnj raw_disconnect(rp); 2345612Swnj sofree(so); 2355612Swnj soisdisconnected(so); 2365612Swnj break; 2375612Swnj 23816974Skarels case PRU_SENSE: 23916974Skarels /* 24016974Skarels * stat: don't bother with a blocksize. 24116974Skarels */ 24216974Skarels return (0); 24316974Skarels 2445612Swnj /* 2455612Swnj * Not supported. 2465612Swnj */ 24716773Sbloom case PRU_RCVOOB: 2485612Swnj case PRU_RCVD: 24916773Sbloom return(EOPNOTSUPP); 25016773Sbloom 25125221Skarels case PRU_LISTEN: 25216773Sbloom case PRU_ACCEPT: 2535612Swnj case PRU_SENDOOB: 2545612Swnj error = EOPNOTSUPP; 2555612Swnj break; 2565612Swnj 2576509Ssam case PRU_SOCKADDR: 25837472Ssklower if (rp->rcb_laddr == 0) { 25937472Ssklower error = EINVAL; 26037472Ssklower break; 26137472Ssklower } 26237472Ssklower len = rp->rcb_laddr->sa_len; 26337472Ssklower bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); 26437472Ssklower nam->m_len = len; 2656509Ssam break; 2666509Ssam 26714122Ssam case PRU_PEERADDR: 26837472Ssklower if (rp->rcb_faddr == 0) { 26937472Ssklower error = ENOTCONN; 27037472Ssklower break; 27137472Ssklower } 27237472Ssklower len = rp->rcb_faddr->sa_len; 27337472Ssklower bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); 27437472Ssklower nam->m_len = len; 27514122Ssam break; 27614122Ssam 2775612Swnj default: 2785612Swnj panic("raw_usrreq"); 2795612Swnj } 28012783Ssam release: 28112783Ssam if (m != NULL) 28212783Ssam m_freem(m); 2835612Swnj return (error); 2845121Swnj } 28537472Ssklower 28637472Ssklower rawintr() {} /* XXX - referenced by locore. will soon go away */ 287