1 /* 2 * Copyright (c) 1980, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)raw_usrreq.c 7.8 (Berkeley) 04/05/90 18 */ 19 20 #include "param.h" 21 #include "mbuf.h" 22 #include "domain.h" 23 #include "protosw.h" 24 #include "socket.h" 25 #include "socketvar.h" 26 #include "errno.h" 27 28 #include "if.h" 29 #include "route.h" 30 #include "netisr.h" 31 #include "raw_cb.h" 32 33 #include "machine/mtpr.h" 34 35 /* 36 * Initialize raw connection block q. 37 */ 38 raw_init() 39 { 40 41 rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 42 rawintrq.ifq_maxlen = IFQ_MAXLEN; 43 } 44 45 46 /* 47 * Raw protocol input routine. Find the socket 48 * associated with the packet(s) and move them over. If 49 * nothing exists for this packet, drop it. 50 */ 51 /* 52 * Raw protocol interface. 53 */ 54 raw_input(m0, proto, src, dst) 55 struct mbuf *m0; 56 register struct sockproto *proto; 57 struct sockaddr *src, *dst; 58 { 59 register struct rawcb *rp; 60 register struct mbuf *m = m0; 61 register int sockets = 0; 62 struct socket *last; 63 64 last = 0; 65 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 66 if (rp->rcb_proto.sp_family != proto->sp_family) 67 continue; 68 if (rp->rcb_proto.sp_protocol && 69 rp->rcb_proto.sp_protocol != proto->sp_protocol) 70 continue; 71 /* 72 * We assume the lower level routines have 73 * placed the address in a canonical format 74 * suitable for a structure comparison. 75 * 76 * Note that if the lengths are not the same 77 * the comparison will fail at the first byte. 78 */ 79 #define equal(a1, a2) \ 80 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 81 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 82 continue; 83 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 84 continue; 85 if (last) { 86 struct mbuf *n; 87 if (n = m_copy(m, 0, (int)M_COPYALL)) { 88 if (sbappendaddr(&last->so_rcv, src, 89 n, (struct mbuf *)0) == 0) 90 /* should notify about lost packet */ 91 m_freem(n); 92 else { 93 sorwakeup(last); 94 sockets++; 95 } 96 } 97 } 98 last = rp->rcb_socket; 99 } 100 if (last) { 101 if (sbappendaddr(&last->so_rcv, src, 102 m, (struct mbuf *)0) == 0) 103 m_freem(m); 104 else { 105 sorwakeup(last); 106 sockets++; 107 } 108 } else 109 m_freem(m); 110 return (sockets); 111 } 112 113 /*ARGSUSED*/ 114 raw_ctlinput(cmd, arg) 115 int cmd; 116 struct sockaddr *arg; 117 { 118 119 if (cmd < 0 || cmd > PRC_NCMDS) 120 return; 121 /* INCOMPLETE */ 122 } 123 124 /*ARGSUSED*/ 125 raw_usrreq(so, req, m, nam, control) 126 struct socket *so; 127 int req; 128 struct mbuf *m, *nam, *control; 129 { 130 register struct rawcb *rp = sotorawcb(so); 131 register int error = 0; 132 int len; 133 134 if (req == PRU_CONTROL) 135 return (EOPNOTSUPP); 136 if (control && control->m_len) { 137 error = EOPNOTSUPP; 138 goto release; 139 } 140 if (rp == 0) { 141 error = EINVAL; 142 goto release; 143 } 144 switch (req) { 145 146 /* 147 * Allocate a raw control block and fill in the 148 * necessary info to allow packets to be routed to 149 * the appropriate raw interface routine. 150 */ 151 case PRU_ATTACH: 152 if ((so->so_state & SS_PRIV) == 0) { 153 error = EACCES; 154 break; 155 } 156 error = raw_attach(so, (int)nam); 157 break; 158 159 /* 160 * Destroy state just before socket deallocation. 161 * Flush data or not depending on the options. 162 */ 163 case PRU_DETACH: 164 if (rp == 0) { 165 error = ENOTCONN; 166 break; 167 } 168 raw_detach(rp); 169 break; 170 171 #ifdef notdef 172 /* 173 * If a socket isn't bound to a single address, 174 * the raw input routine will hand it anything 175 * within that protocol family (assuming there's 176 * nothing else around it should go to). 177 */ 178 case PRU_CONNECT: 179 if (rp->rcb_faddr) { 180 error = EISCONN; 181 break; 182 } 183 nam = m_copym(nam, 0, M_COPYALL, M_WAIT); 184 rp->rcb_faddr = mtod(nam, struct sockaddr *); 185 soisconnected(so); 186 break; 187 188 case PRU_BIND: 189 if (rp->rcb_laddr) { 190 error = EINVAL; /* XXX */ 191 break; 192 } 193 error = raw_bind(so, nam); 194 break; 195 #endif 196 197 case PRU_CONNECT2: 198 error = EOPNOTSUPP; 199 goto release; 200 201 case PRU_DISCONNECT: 202 if (rp->rcb_faddr == 0) { 203 error = ENOTCONN; 204 break; 205 } 206 raw_disconnect(rp); 207 soisdisconnected(so); 208 break; 209 210 /* 211 * Mark the connection as being incapable of further input. 212 */ 213 case PRU_SHUTDOWN: 214 socantsendmore(so); 215 break; 216 217 /* 218 * Ship a packet out. The appropriate raw output 219 * routine handles any massaging necessary. 220 */ 221 case PRU_SEND: 222 if (nam) { 223 if (rp->rcb_faddr) { 224 error = EISCONN; 225 break; 226 } 227 rp->rcb_faddr = mtod(nam, struct sockaddr *); 228 } else if (rp->rcb_faddr == 0) { 229 error = ENOTCONN; 230 break; 231 } 232 error = (*so->so_proto->pr_output)(m, so); 233 m = NULL; 234 if (nam) 235 rp->rcb_faddr = 0; 236 break; 237 238 case PRU_ABORT: 239 raw_disconnect(rp); 240 sofree(so); 241 soisdisconnected(so); 242 break; 243 244 case PRU_SENSE: 245 /* 246 * stat: don't bother with a blocksize. 247 */ 248 return (0); 249 250 /* 251 * Not supported. 252 */ 253 case PRU_RCVOOB: 254 case PRU_RCVD: 255 return(EOPNOTSUPP); 256 257 case PRU_LISTEN: 258 case PRU_ACCEPT: 259 case PRU_SENDOOB: 260 error = EOPNOTSUPP; 261 break; 262 263 case PRU_SOCKADDR: 264 if (rp->rcb_laddr == 0) { 265 error = EINVAL; 266 break; 267 } 268 len = rp->rcb_laddr->sa_len; 269 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); 270 nam->m_len = len; 271 break; 272 273 case PRU_PEERADDR: 274 if (rp->rcb_faddr == 0) { 275 error = ENOTCONN; 276 break; 277 } 278 len = rp->rcb_faddr->sa_len; 279 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); 280 nam->m_len = len; 281 break; 282 283 default: 284 panic("raw_usrreq"); 285 } 286 release: 287 if (m != NULL) 288 m_freem(m); 289 return (error); 290 } 291 292 rawintr() {} /* XXX - referenced by locore. will soon go away */ 293