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