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