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.6 (Berkeley) 04/25/89 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 struct sockproto *proto; 57 struct sockaddr *src, *dst; 58 { 59 register struct rawcb *rp; 60 register struct mbuf *m = m0; 61 struct socket *last; 62 63 last = 0; 64 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 65 if (rp->rcb_proto.sp_family != proto->sp_family) 66 continue; 67 if (rp->rcb_proto.sp_protocol && 68 rp->rcb_proto.sp_protocol != proto->sp_protocol) 69 continue; 70 /* 71 * We assume the lower level routines have 72 * placed the address in a canonical format 73 * suitable for a structure comparison. 74 * 75 * Note that if the lengths are not the same 76 * the comparison will fail at the first byte. 77 */ 78 #define equal(a1, a2) \ 79 (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) 80 if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) 81 continue; 82 if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) 83 continue; 84 if (last) { 85 struct mbuf *n; 86 if (n = m_copy(m, 0, (int)M_COPYALL)) { 87 if (sbappendaddr(&last->so_rcv, src, 88 n, (struct mbuf *)0) == 0) 89 /* should notify about lost packet */ 90 m_freem(n); 91 else 92 sorwakeup(last); 93 } 94 } 95 last = rp->rcb_socket; 96 } 97 if (last) { 98 if (sbappendaddr(&last->so_rcv, src, 99 m, (struct mbuf *)0) == 0) 100 m_freem(m); 101 else 102 sorwakeup(last); 103 } else 104 m_freem(m); 105 } 106 107 /*ARGSUSED*/ 108 raw_ctlinput(cmd, arg) 109 int cmd; 110 struct sockaddr *arg; 111 { 112 113 if (cmd < 0 || cmd > PRC_NCMDS) 114 return; 115 /* INCOMPLETE */ 116 } 117 118 /*ARGSUSED*/ 119 raw_usrreq(so, req, m, nam, rights, control) 120 struct socket *so; 121 int req; 122 struct mbuf *m, *nam, *rights, *control; 123 { 124 register struct rawcb *rp = sotorawcb(so); 125 register int error = 0; 126 int len; 127 128 if (req == PRU_CONTROL) 129 return (EOPNOTSUPP); 130 if (rights && rights->m_len) { 131 error = EOPNOTSUPP; 132 goto release; 133 } 134 if (rp == 0) { 135 error = EINVAL; 136 goto release; 137 } 138 switch (req) { 139 140 /* 141 * Allocate a raw control block and fill in the 142 * necessary info to allow packets to be routed to 143 * the appropriate raw interface routine. 144 */ 145 case PRU_ATTACH: 146 if ((so->so_state & SS_PRIV) == 0) { 147 error = EACCES; 148 break; 149 } 150 error = raw_attach(so, (int)nam); 151 break; 152 153 /* 154 * Destroy state just before socket deallocation. 155 * Flush data or not depending on the options. 156 */ 157 case PRU_DETACH: 158 if (rp == 0) { 159 error = ENOTCONN; 160 break; 161 } 162 raw_detach(rp); 163 break; 164 165 #ifdef notdef 166 /* 167 * If a socket isn't bound to a single address, 168 * the raw input routine will hand it anything 169 * within that protocol family (assuming there's 170 * nothing else around it should go to). 171 */ 172 case PRU_CONNECT: 173 if (rp->rcb_faddr) { 174 error = EISCONN; 175 break; 176 } 177 nam = m_copym(nam, 0, M_COPYALL, M_WAIT); 178 rp->rcb_faddr = mtod(nam, struct sockaddr *); 179 soisconnected(so); 180 break; 181 182 case PRU_BIND: 183 if (rp->rcb_laddr) { 184 error = EINVAL; /* XXX */ 185 break; 186 } 187 error = raw_bind(so, nam); 188 break; 189 #endif 190 191 case PRU_CONNECT2: 192 error = EOPNOTSUPP; 193 goto release; 194 195 case PRU_DISCONNECT: 196 if (rp->rcb_faddr == 0) { 197 error = ENOTCONN; 198 break; 199 } 200 raw_disconnect(rp); 201 soisdisconnected(so); 202 break; 203 204 /* 205 * Mark the connection as being incapable of further input. 206 */ 207 case PRU_SHUTDOWN: 208 socantsendmore(so); 209 break; 210 211 /* 212 * Ship a packet out. The appropriate raw output 213 * routine handles any massaging necessary. 214 */ 215 case PRU_SEND: 216 if (nam) { 217 if (rp->rcb_faddr) { 218 error = EISCONN; 219 break; 220 } 221 rp->rcb_faddr = mtod(nam, struct sockaddr *); 222 } else if (rp->rcb_faddr == 0) { 223 error = ENOTCONN; 224 break; 225 } 226 error = (*so->so_proto->pr_output)(m, so); 227 m = NULL; 228 if (nam) 229 rp->rcb_faddr = 0; 230 break; 231 232 case PRU_ABORT: 233 raw_disconnect(rp); 234 sofree(so); 235 soisdisconnected(so); 236 break; 237 238 case PRU_SENSE: 239 /* 240 * stat: don't bother with a blocksize. 241 */ 242 return (0); 243 244 /* 245 * Not supported. 246 */ 247 case PRU_RCVOOB: 248 case PRU_RCVD: 249 return(EOPNOTSUPP); 250 251 case PRU_LISTEN: 252 case PRU_ACCEPT: 253 case PRU_SENDOOB: 254 error = EOPNOTSUPP; 255 break; 256 257 case PRU_SOCKADDR: 258 if (rp->rcb_laddr == 0) { 259 error = EINVAL; 260 break; 261 } 262 len = rp->rcb_laddr->sa_len; 263 bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); 264 nam->m_len = len; 265 break; 266 267 case PRU_PEERADDR: 268 if (rp->rcb_faddr == 0) { 269 error = ENOTCONN; 270 break; 271 } 272 len = rp->rcb_faddr->sa_len; 273 bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); 274 nam->m_len = len; 275 break; 276 277 default: 278 panic("raw_usrreq"); 279 } 280 release: 281 if (m != NULL) 282 m_freem(m); 283 return (error); 284 } 285 286 rawintr() {} /* XXX - referenced by locore. will soon go away */ 287