1 /* raw_usrreq.c 6.6 85/05/30 */ 2 3 #include "param.h" 4 #include "mbuf.h" 5 #include "domain.h" 6 #include "protosw.h" 7 #include "socket.h" 8 #include "socketvar.h" 9 #include "errno.h" 10 11 #include "if.h" 12 #include "route.h" 13 #include "netisr.h" 14 #include "raw_cb.h" 15 16 #include "../vax/mtpr.h" 17 18 /* 19 * Initialize raw connection block q. 20 */ 21 raw_init() 22 { 23 24 rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 25 rawintrq.ifq_maxlen = IFQ_MAXLEN; 26 } 27 28 /* 29 * Raw protocol interface. 30 */ 31 raw_input(m0, proto, src, dst) 32 struct mbuf *m0; 33 struct sockproto *proto; 34 struct sockaddr *src, *dst; 35 { 36 register struct mbuf *m; 37 struct raw_header *rh; 38 int s; 39 40 /* 41 * Rip off an mbuf for a generic header. 42 */ 43 m = m_get(M_DONTWAIT, MT_HEADER); 44 if (m == 0) { 45 m_freem(m0); 46 return; 47 } 48 m->m_next = m0; 49 m->m_len = sizeof(struct raw_header); 50 rh = mtod(m, struct raw_header *); 51 rh->raw_dst = *dst; 52 rh->raw_src = *src; 53 rh->raw_proto = *proto; 54 55 /* 56 * Header now contains enough info to decide 57 * which socket to place packet in (if any). 58 * Queue it up for the raw protocol process 59 * running at software interrupt level. 60 */ 61 s = splimp(); 62 if (IF_QFULL(&rawintrq)) 63 m_freem(m); 64 else 65 IF_ENQUEUE(&rawintrq, m); 66 splx(s); 67 schednetisr(NETISR_RAW); 68 } 69 70 /* 71 * Raw protocol input routine. Process packets entered 72 * into the queue at interrupt time. Find the socket 73 * associated with the packet(s) and move them over. If 74 * nothing exists for this packet, drop it. 75 */ 76 rawintr() 77 { 78 int s; 79 struct mbuf *m; 80 register struct rawcb *rp; 81 register struct protosw *lproto; 82 register struct raw_header *rh; 83 struct socket *last; 84 85 next: 86 s = splimp(); 87 IF_DEQUEUE(&rawintrq, m); 88 splx(s); 89 if (m == 0) 90 return; 91 rh = mtod(m, struct raw_header *); 92 last = 0; 93 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 94 lproto = rp->rcb_socket->so_proto; 95 if (lproto->pr_domain->dom_family != rh->raw_proto.sp_family) 96 continue; 97 if (lproto->pr_protocol && 98 lproto->pr_protocol != rh->raw_proto.sp_protocol) 99 continue; 100 /* 101 * We assume the lower level routines have 102 * placed the address in a canonical format 103 * suitable for a structure comparison. 104 */ 105 #define equal(a1, a2) \ 106 (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) 107 if ((rp->rcb_flags & RAW_LADDR) && 108 !equal(rp->rcb_laddr, rh->raw_dst)) 109 continue; 110 if ((rp->rcb_flags & RAW_FADDR) && 111 !equal(rp->rcb_faddr, rh->raw_src)) 112 continue; 113 if (last) { 114 struct mbuf *n; 115 if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) { 116 if (sbappendaddr(&last->so_rcv, &rh->raw_src, 117 n, (struct mbuf *)0) == 0) 118 /* should notify about lost packet */ 119 m_freem(n); 120 else 121 sorwakeup(last); 122 } 123 } 124 last = rp->rcb_socket; 125 } 126 if (last) { 127 if (sbappendaddr(&last->so_rcv, &rh->raw_src, 128 m->m_next, (struct mbuf *)0) == 0) 129 m_freem(m->m_next); 130 else 131 sorwakeup(last); 132 (void) m_free(m); /* header */ 133 } else 134 m_freem(m); 135 goto next; 136 } 137 138 /*ARGSUSED*/ 139 raw_ctlinput(cmd, arg) 140 int cmd; 141 caddr_t arg; 142 { 143 144 if (cmd < 0 || cmd > PRC_NCMDS) 145 return; 146 /* INCOMPLETE */ 147 } 148 149 /*ARGSUSED*/ 150 raw_usrreq(so, req, m, nam, rights) 151 struct socket *so; 152 int req; 153 struct mbuf *m, *nam, *rights; 154 { 155 register struct rawcb *rp = sotorawcb(so); 156 register int error = 0; 157 158 if (rights && rights->m_len) { 159 error = EOPNOTSUPP; 160 goto release; 161 } 162 if (rp == 0 && req != PRU_ATTACH) { 163 error = EINVAL; 164 goto release; 165 } 166 switch (req) { 167 168 /* 169 * Allocate a raw control block and fill in the 170 * necessary info to allow packets to be routed to 171 * the appropriate raw interface routine. 172 */ 173 case PRU_ATTACH: 174 if ((so->so_state & SS_PRIV) == 0) { 175 error = EACCES; 176 break; 177 } 178 if (rp) { 179 error = EINVAL; 180 break; 181 } 182 error = raw_attach(so); 183 break; 184 185 /* 186 * Destroy state just before socket deallocation. 187 * Flush data or not depending on the options. 188 */ 189 case PRU_DETACH: 190 if (rp == 0) { 191 error = ENOTCONN; 192 break; 193 } 194 raw_detach(rp); 195 break; 196 197 /* 198 * If a socket isn't bound to a single address, 199 * the raw input routine will hand it anything 200 * within that protocol family (assuming there's 201 * nothing else around it should go to). 202 */ 203 case PRU_CONNECT: 204 if (rp->rcb_flags & RAW_FADDR) { 205 error = EISCONN; 206 break; 207 } 208 raw_connaddr(rp, nam); 209 soisconnected(so); 210 break; 211 212 case PRU_CONNECT2: 213 error = EOPNOTSUPP; 214 goto release; 215 216 case PRU_BIND: 217 if (rp->rcb_flags & RAW_LADDR) { 218 error = EINVAL; /* XXX */ 219 break; 220 } 221 error = raw_bind(so, nam); 222 break; 223 224 case PRU_DISCONNECT: 225 if ((rp->rcb_flags & RAW_FADDR) == 0) { 226 error = ENOTCONN; 227 break; 228 } 229 if (rp->rcb_route.ro_rt) 230 rtfree(rp->rcb_route.ro_rt); 231 raw_disconnect(rp); 232 soisdisconnected(so); 233 break; 234 235 /* 236 * Mark the connection as being incapable of further input. 237 */ 238 case PRU_SHUTDOWN: 239 socantsendmore(so); 240 break; 241 242 /* 243 * Ship a packet out. The appropriate raw output 244 * routine handles any massaging necessary. 245 */ 246 case PRU_SEND: 247 if (nam) { 248 if (rp->rcb_flags & RAW_FADDR) { 249 error = EISCONN; 250 break; 251 } 252 raw_connaddr(rp, nam); 253 } else if ((rp->rcb_flags & RAW_FADDR) == 0) { 254 error = ENOTCONN; 255 break; 256 } 257 /* 258 * Check for routing. If new foreign address, or 259 * no route presently in use, try to allocate new 260 * route. On failure, just hand packet to output 261 * routine anyway in case it can handle it. 262 */ 263 if ((rp->rcb_flags & RAW_DONTROUTE) == 0) 264 if (!equal(rp->rcb_faddr, rp->rcb_route.ro_dst) || 265 rp->rcb_route.ro_rt == 0) { 266 if (rp->rcb_route.ro_rt) { 267 RTFREE(rp->rcb_route.ro_rt); 268 rp->rcb_route.ro_rt = NULL; 269 } 270 rp->rcb_route.ro_dst = rp->rcb_faddr; 271 rtalloc(&rp->rcb_route); 272 } 273 error = (*so->so_proto->pr_output)(m, so); 274 m = NULL; 275 if (nam) 276 rp->rcb_flags &= ~RAW_FADDR; 277 break; 278 279 case PRU_ABORT: 280 raw_disconnect(rp); 281 sofree(so); 282 soisdisconnected(so); 283 break; 284 285 case PRU_SENSE: 286 /* 287 * stat: don't bother with a blocksize. 288 */ 289 return (0); 290 291 /* 292 * Not supported. 293 */ 294 case PRU_CONTROL: 295 case PRU_RCVOOB: 296 case PRU_RCVD: 297 return(EOPNOTSUPP); 298 299 case PRU_ACCEPT: 300 case PRU_SENDOOB: 301 error = EOPNOTSUPP; 302 break; 303 304 case PRU_SOCKADDR: 305 bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), 306 sizeof (struct sockaddr)); 307 nam->m_len = sizeof (struct sockaddr); 308 break; 309 310 case PRU_PEERADDR: 311 bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t), 312 sizeof (struct sockaddr)); 313 nam->m_len = sizeof (struct sockaddr); 314 break; 315 316 default: 317 panic("raw_usrreq"); 318 } 319 release: 320 if (m != NULL) 321 m_freem(m); 322 return (error); 323 } 324